The standard method for passing data between Fortran routines and C procedures is by reference. To a C procedure, a Fortran subroutine or function call looks like a procedure call with all arguments represented by pointers. The only peculiarity is the way Fortran handles character strings and functions as arguments and as the return value from a CHARACTER*n function.
For simple data types (not COMPLEX or CHARACTER strings), define or pass each associated argument in the C routine as a pointer:
Table 11–3 Passing Simple Data Types
Fortran calls C |
C calls Fortran |
||
---|---|---|---|
|
|
Pass a Fortran COMPLEX data item as a pointer to a C struct of two float or two double data types:
Table 11–4 Passing COMPLEX Data Types
Fortran calls C |
C calls Fortran |
||
---|---|---|---|
|
|
In 64-bit environments, COMPLEX values are returned in registers.
Passing strings between C and Fortran routines is not recommended because there is no standard interface. However, note the following:
All C strings are passed by reference.
Fortran calls pass an additional argument for every argument with character type in the argument list. The extra argument gives the length of the string and is equivalent to a C long int passed by value. (This is implementation dependent.) The extra string-length arguments appear after the explicit arguments in the call.
A Fortran call with a character string argument is shown in the next example with its C equivalent:
Table 11–5 Passing a CHARACTER String
Fortran call: |
C equivalent: |
||
---|---|---|---|
|
|
If the length of the string is not needed in the called routine, the extra arguments may be ignored. However, note that Fortran does not automatically terminate strings with the explicit null character that C expects. This must be added by the calling program.
The call for a character array looks identical to the call for a single character variable. The starting address of the array is passed, and the length that it uses is the length of a single element in the array.
Array subscripts in C start with 0.
Table 11–6 Passing a One-Dimensional Array
Fortran calls C |
C calls Fortran |
||
---|---|---|---|
|
|
Rows and columns between C and Fortran are switched.
Table 11–7 Passing a Two-Dimensional Array
Fortran calls C |
C calls Fortran |
||
---|---|---|---|
|
|
C and Fortran 95 derived types can be passed to each other’s routines as long as the corresponding elements are compatible.( f95 accepts legacy STRUCTURE statements.)
Table 11–8 Passing Legacy FORTRAN 77 STRUCTURE Records
Fortran calls C |
C calls Fortran |
||
---|---|---|---|
|
|
Note that Fortran 77 (VAX) structures always have the same alignment as C structures on all platforms. However, the alignment changes between platforms.
Table 11–9 Passing Fortran 95 Derived Types
Fortran 95 calls C |
C calls Fortran 95 |
||
---|---|---|---|
|
|
Note that the Fortran 95 standard requires the SEQUENCE statement in the definition of the derived type to insure that storage sequence order be preserved by the compiler.
The components of a numeric sequence type are aligned on word (4-byte) boundaries on all platforms by default. This matches the alignment of C structures on x86 platforms, but differs from the alignment of C structures on SPARC platforms. Use the -aligncommon option to change the alignment of numeric sequence types to match C structures. Use -aligncommon=8 to match 32–bit SPARC C structures, -aligncommon=16 to match 64–bit SPARC.
Derived types not explicitly declared with SEQUENCE have the same alignment as C structures on SPARC platforms, but differ on x86 platforms. This alignment cannot be changed with a compiler option.
A FORTRAN 77 (Cray) pointer can be passed to a C routine as a pointer to a pointer because the Fortran routine passes arguments by reference.
Table 11–10 Passing a FORTRAN 77 (Cray) POINTER
Fortran calls C |
C calls Fortran |
||
---|---|---|---|
|
|
C pointers are compatible with Fortran 95 scalar pointers, but not array pointers.
Fortran 95 calls C with a scalar pointer |
||
---|---|---|
Fortran 95 routine:
C routine:
|
The major difference between Cray and Fortran 95 pointers is that the target of a Cray pointer is always named. In many contexts, declaring a Fortran 95 pointer automatically identifies its target. Also, an explicit INTERFACE block is required for the called C routine.
To pass a Fortran 95 pointer to an array or array section requires a specific INTERFACE block, as in this example:
Fortran 95 routine: INTERFACE SUBROUTINE S(P) integer P(*) END SUBROUTINE S END INTERFACE integer, target:: A(0:9) integer, pointer :: P(:) P => A(0:9:2) !! pointer selects every other element of A call S(P) ... C routine: void s_(int p[]) { /* change middle element */ p[2] = 444; } |
Note that since the C routine S is not a Fortran 95 routine, you cannot define it to be assumed shape (integer P(:)) in the interface block. If the C routine needs to know the actual size of the array it must be passed as an argument to the C routine.
Again, keep in mind that subscripting between C and Fortran differs in that C arrays start at subscript 0.