Fortran Programming Guide

Passing Data Arguments by Reference

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.

Simple Data Types

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

COMPLEX Data

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.

Character Strings

Passing strings between C and Fortran routines is not recommended because there is no standard interface. However, note the following:

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.

One-Dimensional Arrays

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

...

Two-Dimensional Arrays

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

...

Structures

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

...

Pointers

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.