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-4 Passing Simple Data Types
Fortran calls C |
C calls Fortran |
---|---|
integer i real r external CSim i = 100 call CSim(i,r) ... ---------------------------- void csim_(int *i, float *r) { *r = *i; }
|
int i=100; float r; extern void fsim_(int *i, float *r); fsim_(&i, &r); ... ------------------------------ subroutine FSim(i,r) integer i real r r = i return end |
Pass a Fortran COMPLEX data item as a pointer to a C struct of two float or two double data types:
Table 11-5 Passing COMPLEX Data Types
Fortran calls C |
C calls Fortran |
---|---|
complex w double complex z external CCmplx call CCmplx(w,z) ... ------------------------------ struct cpx {float r, i;}; struct dpx {double r,i;}; void ccmplx_( struct cpx *w, struct dpx *z) { w -> r = 32.; w -> i = .007; z -> r = 66.67; z -> i = 94.1; } |
struct cpx {float r, i;}; struct cpx d1; struct cpx *w = &d1; struct dpx {double r, i;}; struct dpx d2; struct dpx *z = &d2; fcmplx_( w, z ); ... --------------- subroutine FCmplx( w, z ) complex w double complex z w = (32., .007) z = (66.67, 94.1) return end |
In 64-bit environments and compiling with -xarch=v9, 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-6 Passing a CHARACTER string
Fortran call: |
C equivalent: |
---|---|
CHARACTER*7 S INTEGER B(3) ... CALL CSTRNG( S, B(2) ) ... |
char s[7]; long b[3]; ... cstrng_( s, &b[1], 7L ); ... |
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.
Array subscripts in C start with 0.
Table 11-7 Passing a One-Dimensional Array
Fortran calls C |
C calls Fortran |
---|---|
integer i, Sum integer a(9) external FixVec ... call FixVec ( a, Sum ) ... ------------------------------ void fixvec_ ( int v[9], int *sum ) { int i; *sum = 0; for ( i = 0; i <= 8; i++ ) *sum = *sum + v[i]; } |
extern void vecref_ ( int[], int * ); ... int i, sum; int v[9] = ... vecref_( v, &sum ); ... ------------------------------ subroutine VecRef( v, total) integer i, total, v(9) total = 0 do i = 1,9 total = total + v(i) end do ... |
Rows and columns between C and Fortran are switched.
Table 11-8 Passing a Two-Dimensional Array
Fortran calls C |
C calls Fortran |
---|---|
REAL Q(10,20) ... Q(3,5) = 1.0 CALL FIXQ(Q) ... ------------------------------ void fixq_( float a[20][10] ) { ... a[5][3] = a[5][3] + 1.; ... } |
extern void qref_( int[][10], int *); ... int m[20][10] = ... ; int sum; ... qref_( m, &sum ); ... ------------------------------ SUBROUTINE QREF(A,TOTAL) INTEGER A(10,20), TOTAL DO I = 1,10 DO J = 1,20 TOTAL = TOTAL + A(I,J) END DO END DO ... |
C and FORTRAN 77 structures and Fortran 90 derived types can be passed to each other's routines as long as the corresponding elements are compatible.
Table 11-9 Passing FORTRAN 77 STRUCTURE Records
Fortran calls C |
C calls Fortran |
---|---|
STRUCTURE /POINT/ REAL X, Y, Z END STRUCTURE RECORD /POINT/ BASE EXTERNAL FLIP ... CALL FLIP( BASE ) ... ------------------------------ struct point { float x,y,z; }; void flip_( struct point *v; ) { float t; t = v -> x; v -> x = v -> y; v -> y = t; v -> z = -2.*(v -> z); } |
struct point { float x,y,z; }; void fflip_ ( struct point *) ; ... struct point d; struct point *ptx = &d; ... fflip_ (ptx); ... ------------------------------ SUBROUTINE FFLIP(P) STRUCTURE /POINT/ REAL X,Y,Z END STRUCTURE RECORD /POINT/ P REAL T T = P.X P.X = P.Y P.Y = T P.Z = -2.*P.Z ... |
Table 11-10 Passing Fortran 90 Derived Types
Fortran 90 calls C |
C calls Fortran 90 |
---|---|
TYPE point SEQUENCE REAL :: x, y, z END TYPE point TYPE (point) base EXTERNAL flip ... CALL flip( base) ... ------------------------------ struct point { float x,y,z; }; void flip_( struct point *v; ) { float t; t = v -> x; v -> x = v -> y; v -> y = t; v -> z = -2.*(v -> z); }
|
struct point { float x,y,z; }; extern void fflip_ ( struct point *) ; ... struct point d; struct point *ptx = &d; ... fflip_ (ptx); ... ------------------------------ SUBROUTINE FFLIP( P ) TYPE POINT REAL :: X, Y, Z END TYPE POINT TYPE (POINT) P REAL :: T T = P%X P%X = P%Y P%Y = T P%Z = -2.*P%Z ...
|
A FORTRAN 77 pointer can be passed to a C routine as a pointer to a pointer because the Fortran routine passes arguments by reference.
Table 11-11 Passing a FORTRAN 77 POINTER
Fortran calls C |
C calls Fortran |
---|---|
REAL X POINTER (P2X, X) EXTERNAL PASS P2X = MALLOC(4) X = 0. CALL PASS(X) ... ------------------------------ void pass_(x) int **x; { **x = 100.1; } |
extern void fpass_; ... float *x; float **p2x; fpass_(p2x) ; ... ------------------------------ SUBROUTINE FPASS (P2X) REAL X POINTER (P2X, X) X = 0. ... |
C pointers are compatible with Fortran 90 (release 2.0) scalar pointers, but not array pointers.