Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29253 Discussions

Mapping of types between Fortran and C++

alexanpe99
Beginner
647 Views

I'm still trying to port a Fortran and C++ system from windows to Linux, finally managed to reach the stage of testing an executable. However havingsome problems with passing data between the langugaes on Linux. The intel compiler is used on both platforms for both languages.

The main data being passed takes the form of a number of linked list. Each is initalised in Fortran and the top level node is access on the C++ by an extern. The C++ side can then traverses the list as required. There are a number of types of list, some of which I've managed to get to work on Linux and some I have not, all work on Windows. I will give you an example of what of one that appear to work after a few tweaks and one that does not.

The working list is of Sw types, the fortran type definition and then the C++ struct are defined as follows in the original Windows code.
[bash]type Sw
        Sequence
        character,pointer       ::Gname(:)           ! pekare till gruppnamnstring
        character,pointer       ::name(:)            ! pekare till namnstring
        integer                 ::val                   
        character,pointer       ::conditions(:)      ! pekare till vilkorsstring                     
        character,pointer       ::optionsa(:)        ! kan anta v?rde 0 till errmax
        type(Sw),pointer        ::next               ! n?sta element i listan
        integer                 ::number             ! placering i listan, sist=0
        integer                 ::rec                ! index f?r Soft omkalkylering av parametrar
        integer                 ::frec               ! index f?r omkalkylering av parametrar
        integer                 ::UserLevel          ! Indicator for use in menues
end type Sw[/bash]
[bash] struct FILL{
        int fill_1;
        int fill_2;
        int fill_3;
        int fill_4;
        int fill_5;
        int fill_6;
        int fill_7;
        int fill_8;
};
struct Sw{
        char*   gname;  FILL    gname_stuff;
        char*   name;    FILL    name_stuff;
        int*    val;
        char*   conditions;     FILL    cond_stuff;
        char*   options;        FILL    opt_stuff;
        Sw*     next;
        int      number;
        int      rec;
        int      frec;
        int    UserLevel;
 };[/bash]

To make the structure readable on Linux I have made FILL contain 16 ints, rather than 8 as here. However the int* val, also caused a problem which I was only able to fix by making the fortran definition integer(8). Although this appears to work, I'm concerned whether this is the correct change to make or not. So my first question is do these changes appear sensible.

I'm having even more trouble with the another type, which is definited as follows:
[bash]type GDXT
    character,pointer           ::gname(:)            ! pekare till namnstring
        character,pointer       ::name(:)             ! pekare till namnstring
        character,pointer       ::unit(:)             ! pekare till enhetsstring
        character,pointer       ::conditions(:)       ! pekare till vilkorsstring                     
        integer                 ::val                 ! pointer till real*8(:)
        integer                 ::flags               ! Pointer to the flags aray
        integer,pointer         ::flag(:)             ! pointer till interger(:)
        integer                 ::tabind              ! Type(E) pointer
        type(GDXT),pointer      ::next                ! n?sta element i listan
        integer                 ::number              ! plats i listan
        integer                 ::ininumflag          ! Number of flags in the flag array
        integer                 ::UserLevel           ! Indicator for use in menues
        Integer                 ::VectorId            ! Indicator for use of vector identification 
        Integer                 ::VectorPosition      ! position in vector id
        Integer                 ::nc_type             ! type of Variable NC (1) or not (0)
        Integer                 ::process_type        ! enumerator for process identification 
end type GDXT
[/bash]
[bash] struct GD{
        char*   gname;       FILL    gname_stuff;
        char*   name;        FILL    name_stuff;
        char*   unit;        FILL    unit_stuff;
        char*   conditions;  FILL    cond_stuff;
        float*  val;
        int**   flag;
        int*    flags;       FILL    flags_stuff;
        int*    tabind;
        GD*     next;
        int     number;
        int     ininumflag;
        int     UserLevel;
        int     VectorId;
        int     NC_Type;
        int     Process_Type;
 };[/bash]
The structure of the linked list is accessible correctly in C++, after applying similar changes as before, i.e. FILL to 16 ints and val, flags and tabind in the fortran type to integer(8). This suggests to me that the correct number of bytes has been specified in the C struct, however there are problems with the address obtained for val, causing a segmenation fault on attempted access to it. The flag and flags setup appears strangely inverted to me, but it does work in the Windows build and changing it around doesn't seem to resolve the problem on the Linux build. After trying a fair bit of guess work and trial and error I'm now a bit stuck.

Thanks for your help.

Peter
0 Kudos
2 Replies
Steven_L_Intel1
Employee
647 Views
Do not use (:) when declaring arrays that are meant to interoperate with C, as that won't work. I would suggest that you read the Fortran 2008 standard's section on C Interoperability (Chapter 15) and use the types and kinds provided. For the various pointers, you can use TYPE(C_PTR) and then use the C_F_POINTER and C_LOC module intrinsics (from module ISO_C_BINDING) to convert to and from Fortran pointers. You should also declare the type as BIND(C) which will ensure that the layout matches the companion C processor.
0 Kudos
alexanpe99
Beginner
647 Views

Steve,

Thanks for your reply. I'd already looked at the C Interoperability information in the Intel documentation and realised that the approach in the code above did not match that outlined. I was hoping that a smaller change could be made to resolve the problem, partially asI'm not sure how to handle a some of the types (even after reading those documents). For example gname, where I need an unknown size array of CHARACTER(C_CHAR). Also the 'next' member variable needs to be a pointer to a fortran type and can't see how to accommodate that. As there are 1000s of lines that use these types (and other types that are similar) so it's going to be problematic if code changes are required to access them in a different manner.

Thanks again.

Peter

0 Kudos
Reply