Sun Studio 12: Fortran Programming Guide

Chapter 11 C-Fortran Interface

This chapter treats issues regarding Fortran and C interoperability and applies only to the specifics of the Sun Studio Fortran 95, and C compilers.

11.9 Fortran 2003 Interoperability With C discusses briefly the C binding features proposed in Section 15 of the Fortran 2003 standard. (The standard is available at the international Fortran standards web site, http://www.j3-fortran.org). The Fortran 95 compiler implements these features, as described in the standard.

Except where noted, 32-bit x86 processors are treated the same as 32-bit SPARC processors. The same is true for 64-bit x86 and 64-bit SPARC processors, with the exception that REAL*16 and COMPLEX*32 data types are not defined for x86 systems and are only available on SPARC.

11.1 Compatibility Issues

Most C-Fortran interfaces must agree in all of these aspects:

Some C-Fortran interfaces must also agree on:

11.1.1 Function or Subroutine?

The word function has different meanings in C and Fortran. Depending on the situation, the choice is important:

When a Fortran routine calls a C function:

When a C function calls a Fortran subprogram:

11.1.2 Data Type Compatibility

Table 11–2 summarizes the data sizes and default alignments for Fortran 95 data types compared with C. It assumes no compilation options affecting alignment or promoting default data sizes are applied. Note the following:

Table 11–1 Data Sizes and Alignment—(in Bytes) Pass by Reference ( f95 and cc)

Fortran 95 Data Type 

C Data Type 

Size 

Alignment 

BYTE x

char x

CHARACTER x

unsigned char x ;

 

CHARACTER (LEN=n) x

unsigned char x[n] ;

n

COMPLEX x

struct {float r,i;} x;

 

COMPLEX (KIND=4) x

COMPLEX (KIND=8) x

COMPLEX (KIND=16) x (SPARC)

struct {float r,i;} x;

struct {double dr,di;} x;

struct {long double, dr,di;} x;

16 

32 

4/8 

4/8/16 

DOUBLE COMPLEX x

struct {double dr, di;} x;

16 

4/8 

DOUBLE PRECISION x

double x ;

REAL x

float x ;

 

REAL (KIND=4) x

REAL (KIND=8) x

REAL (KIND=16) x (SPARC)

float x ;

double x ;

long double x ;

16 

4/8 

4/8/16 

INTEGER x

int x ;

 

INTEGER (KIND=1) x

INTEGER (KIND=2) x

INTEGER (KIND=4) x

INTEGER (KIND=8) x

signed char x ;

short x ;

int x ;

long long int x;

LOGICAL x

int x ;

 

LOGICAL (KIND=1) x

LOGICAL (KIND=2) x

LOGICAL (KIND=4) x

LOGICAL (KIND=8) x

signed char x ;

short x ;

int x ;

long long int x;

11.1.3 Case Sensitivity

C and Fortran take opposite perspectives on case sensitivity:

The f95 default is to ignore case by converting subprogram names to lowercase. It converts all uppercase letters to lowercase letters, except within character-string constants.

There are two usual solutions to the uppercase/lowercase problem:

Use one of these two solutions, but not both.

Most examples in this chapter use all lowercase letters for the name in the C function, and do not use the f95 -U compiler option.

11.1.4 Underscores in Routine Names

The Fortran compiler normally appends an underscore (_) to the names of subprograms appearing both at entry point definition and in calls. This convention differs from C procedures or external variables with the same user-assigned name. Almost all Fortran library procedure names have double leading underscores to reduce clashes with user-assigned subroutine names.

There are three usual solutions to the underscore problem:

Use only one of these solutions.

The examples in this chapter could use the BIND(C) attribute declaration to avoid underscores. BIND(C) declares the C external functions that can be called from Fortran, and the Fortran routines that can be called from C as arguments. The Fortran compiler does not append an underscore as it ordinarily does with external names. The BIND(C) must appear in each subprogram that contains such a reference. The conventional usage is:


       FUNCTION ABC
        EXTERNAL XYZ
        BIND(C) ABC, XYZ

Here the user has specified not only that XYZ is an external C function, but that the Fortran caller, ABC, should be callable from a C function. If you use BIND(C), the C function does not need an underscore appended to the function name.

11.1.5 Argument-Passing by Reference or Value

In general, Fortran routines pass arguments by reference. In a call, if you enclose an argument with the nonstandard function %VAL(), the calling routine passes it by value.

The standard Fortran 95 way to pass arguments by value is the VALUE attribute and through INTERFACE blocks. See 11.4 Passing Data Arguments by Value.

In general, C passes arguments by value. If you precede an argument by the ampersand operator (&), C passes the argument by reference using a pointer. C always passes arrays and character strings by reference.

11.1.6 Argument Order

Except for arguments that are character strings, Fortran and C pass arguments in the same order. However, for every argument of character type, the Fortran routine passes an additional argument giving the length of the string. These are long int quantities in C, passed by value.

The order of arguments is:

Example:

This Fortran code fragment:  

Is equivalent to this in C:  


CHARACTER*7 S
INTEGER B(3)
...
 CALL SAM( S, B(2) )

char s[7];
int b[3];
...
sam_( s, &b[1], 7L ) ; 

11.1.7 Array Indexing and Order

Array indexing and order differ between Fortran and C.

11.1.7.1 Array Indexing

C arrays always start at zero, but by default Fortran arrays start at 1. There are two usual ways of approaching indexing.


      INTEGER B(0:2)

This way, the Fortran element B(1) is equivalent to the C element b[1].

11.1.7.2 Array Order

Fortran arrays are stored in column-major order: A(3,2)


A(1,1)  A(2,1)  A(3,1)  A(1,2)  A(2,2)  A(3,2)

C arrays are stored in row-major order: A[3][2]


A[0][0] A[0][1] A[1][0] A[1][1] A[2][0] A[2][1]

This does not present a problem for one-dimensional arrays. However, with multi-dimensional arrays, be aware of how subscripts appear and are used in all references and declarations—some adjustments might be necessary.

For example, it may be confusing to do part of a matrix manipulation in C and the rest in Fortran. It might be preferable to pass an entire array to a routine in the other language and perform all the matrix manipulation in that routine to avoid doing part in C and part in Fortran.

11.1.8 File Descriptors and stdio

Fortran I/O channels are in terms of unit numbers. The underlying SunOS operating system does not deal with unit numbers but with file descriptors. The Fortran runtime system translates from one to the other, so most Fortran programs do not have to recognize file descriptors.

Many C programs use a set of subroutines, called standard I/O (or stdio). Many functions of Fortran I/O use standard I/O, which in turn uses operating system I/O calls. Some of the characteristics of these I/O systems are listed in the following table.

Table 11–2 Comparing I/O Between Fortran and C

 

Fortran Units  

Standard I/O File Pointers  

File Descriptors  

Files Open  

Opened for reading and writing 

Opened for reading, or for writing, or for both; or opened for appending; See open(2)

Opened for reading, or for writing, or opened for both 

Attributes  

Formatted or unformatted 

Always unformatted, but can be read or written with format-interpreting routines 

Always unformatted 

Access  

Direct or sequential 

Direct access if the physical file representation is direct access, but can always be read sequentially 

Direct access if the physical file representation is direct access, but can always be read sequentially 

Structure  

Record 

Byte stream 

Byte stream 

Form  

Arbitrary nonnegative integers from 0-2147483647 

Pointers to structures in the user’s address space 

Integers from 0-1023 

11.1.9 Libraries and Linking With the f95 Command

To link the proper Fortran and C libraries, use the f95 command to invoke the linker.

Example 1: Use the compiler to do the linking:


demo% cc -c someCroutine.c
demo% f95 theF95routine.f someCroutine.o  <- The linking step
demo% a.out
 4.0 4.5
 8.0 9.0
demo%

11.2 Fortran Initialization Routines

Main programs compiled by f95 call dummy initialization routine f90_init in the library at program start up. The routines in the library are dummies that do nothing. The calls the compilers generate pass pointers to the program’s arguments and environment. These calls provide software hooks you can use to supply your own routines, in C, to initialize a program in any customized manner before the program starts up.

One possible use of these initialization routines to call setlocale for an internationalized Fortran program. Because setlocale does not work if libc is statically linked, only Fortran programs that are dynamically linked with libc should be internationalized.

The source code for the init routines in the library is


void f90_init(int *argc_ptr, char ***argv_ptr, Char ***envp_ptr) {}

f90_init is called by f95 main programs. The arguments are set to the address of argc, the address of argv, and the address of envp.

11.3 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.

11.3.1 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–3 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 

11.3.2 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–4 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, COMPLEX values are returned in registers.

11.3.3 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–5 Passing a CHARACTER String

Fortran call:  

C equivalent:  


CHARACTER*7 S
INTEGER B(3)
...
CALL CSTRNG( S, B(2) )
... 

char s[7];
int 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.

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.

11.3.4 One-Dimensional Arrays

Array subscripts in C start with 0.

Table 11–6 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
  ... 

11.3.5 Two-Dimensional Arrays

Rows and columns between C and Fortran are switched.

Table 11–7 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
  ...

11.3.6 Structures

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  


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
  ...

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  


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
     SEQUENCE
     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
    ...

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.

11.3.7 Pointers

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  


REAL X
POINTER (P2X, X)
EXTERNAL PASS
P2X = MALLOC(4)
X = 0.
CALL PASS(P2X)
...

------------------------------

void pass_(p)
> float **p;
{
  **p = 100.1;
}

extern void fpass_( float** );
...
float *p2x;
...
 fpass_(&p2x) ;
...

------------------------------

SUBROUTINE FPASS (P2X)
  REAL X
  POINTER (P2X, X)
  X = 0.
  ...

C pointers are compatible with Fortran 95 scalar pointers, but not array pointers.

Fortran 95 calls C with a scalar pointer  

Fortran 95 routine:


INTERFACE
  SUBROUTINE PASS(P)
   REAL, POINTER :: P
  END SUBROUTINE
END INTERFACE

 REAL, POINTER :: P2X
 ALLOCATE (P2X)
 P2X = 0
 CALL PASS(P2X)
 PRINT*, P2X
END

C routine:


void pass_(p);
float **p;
{
  **p = 100.1;
}

 

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.

11.4 Passing Data Arguments by Value

Fortran 95 programs should use the VALUE attribute in dummy arguments when being called from C, and supply an INTERFACE block for C routines that are called from Fortran 95.

Table 11–11 Passing Simple Data Elements Between C and Fortran 95

Fortran 95 calls C  

C calls Fortran 95  


PROGRAM callc
INTERFACE 
 INTEGER FUNCTION crtn(I)
  BIND(C) crtn 
  INTEGER, VALUE, INTENT(IN) :: I 
 END FUNCTION crtn
END INTERFACE 
M = 20 
MM = crtn(M) 
WRITE (*,*) M, MM
END PROGRAM

---------------------------------

int crtn(int x)
{
  int y;
  printf("%d input \n", x);
  y = x + 1;
  printf("%d returning \n",y);
  return(y);
}

---------------------------------

Results:
20 input
21 returning
20 21

#include <stdlib.h>
int main(int ac, char *av[]) {
  to_fortran_(12);
}

--------------------------------

SUBROUTINE to_fortran(i)
  INTEGER, VALUE :: i
  PRINT *, i
END

Note that if the C routine will be called with different data types as an actual argument, you should include a !$PRAGMA IGNORE_TKR I in the interface block to inhibit the compiler from requiring a match in type, kind, and rank between the actual and dummy argument.

With legacy Fortran 77, call by value was available only for simple data, and only by Fortran 77 routines calling C routines. There was no way for a C routine to call a Fortran 77 routine and pass arguments by value. Arrays, character strings, or structures are best passed by reference.

To pass a value to a C routine from a Fortran 77 routine, use the nonstandard Fortran function %VAL(arg) as an argument in the call.

In the following example, the Fortran 77 routine passes x by value and y by reference. The C routine incremented both x and y, but only y is changed.

Fortran calls C  

Fortran routine:


REAL x, y
x = 1.
y = 0.
PRINT *, x,y
CALL value( %VAL(x), y)
PRINT *, x,y
END

C routine:


void value_( float x, float *y)
{
  printf("%f, %f\n",x,*y);
  x = x + 1.;
  *y = *y + 1.;
  printf("%f, %f\n",x,*y);
}

Compiling and running produces output:


1.00000 0.          x and y from Fortran
1.000000, 0.000000  x and y from C
2.000000, 1.000000  new x and y from C
1.00000 1.00000     new x and y from Fortran

11.5 Functions That Return a Value

A Fortran function that returns a value of type BYTE , INTEGER, REAL, LOGICAL, DOUBLE PRECISION, or REAL*16 is equivalent to a C function that returns a compatible type (see Table 11–1). There are two extra arguments for the return values of character functions, and one extra argument for the return values of complex functions.

11.5.1 Returning a Simple Data Type

The following example returns a REAL or float value. BYTE, INTEGER, LOGICAL, DOUBLE PRECISION, and REAL*16 are treated in a similar way:

Table 11–12 Functions Returning a REAL or Float Value

Fortran calls C  

C calls Fortran  


real ADD1, R, S
external ADD1
R = 8.0
S = ADD1( R )
...

------------------------------

float add1_( pf )
float *pf;
{
   float f ;
   f = *pf;
   f++;
   return ( f );
}

float r, s;
extern float fadd1_() ;
r = 8.0;
s = fadd1_( &r );
...

------------------------------

real function fadd1 (p)
  real p
  fadd1 = p + 1.0
  return
end

11.5.2 Returning COMPLEX Data

The situation for interoperability of COMPLEX data differs between 32-bit implementations and 64-bit SPARC implementations.

11.5.2.1 32-bit Platforms

A Fortran function returning COMPLEX or DOUBLE COMPLEX on 32-bit platforms is equivalent to a C function with an additional first argument that points to the return value in memory. The general pattern for the Fortran function and its corresponding C function is:

Fortran function  

C function  


COMPLEX FUNCTION CF( a1,a2,...,an)

cf_ (return, a1, a2, ..., an)
 struct { float r, i; } *return

Table 11–13 Function Returning COMPLEX Data (32–bit SPARC)

Fortran calls C  

C calls Fortran  


COMPLEX U, V, RETCPX
EXTERNAL RETCPX
U = ( 7.0, -8.0)
V = RETCPX(U)
...

------------------------------

struct complex { float r, i; };
void retcpx_( temp, w )
struct complex *temp, *w;
{
   temp->r = w->r + 1.0;
   temp->i = w->i + 1.0;
   return;
}

struct complex { float r, i; };
struct complex c1, c2;<
struct complex *u=&c1, *v=&c2;
extern retfpx_();
u -> r = 7.0;
u -> i = -8.0;
retfpx_( v, u );
...

------------------------------

COMPLEX FUNCTION RETFPX(Z)
  COMPLEX Z
  RETFPX = Z + (1.0, 1.0)
  RETURN
END

11.5.2.2 64–bit SPARC Platforms

In 64-bit SPARC environments, COMPLEX values are returned in floating-point registers: COMPLEX and DOUBLE COMPLEX in %f0 and %f1, and COMPLEX*32 in %f0, %f1, %f2, and %f3. For 64–bit SPARC, a C function returning a structure whose fields are all floating-point types will return the structure in the floating-point registers if at most 4 such registers are needed to do so.The general pattern for the Fortran function and its corresponding C function on 64–bit SPARC platforms is:

Fortran function  

C function  

COMPLEX FUNCTION CF(a1, a2, ..., an)

struct {float r,i;} cf_ (a1, a2, ..., an)

Table 11–14 Function Returning COMPLEX Data (64–bit SPARC)

Fortran calls C  


COMPLEX U, V, RETCPX
EXTERNAL RETCPX
U = ( 7.0, -8.0)
V = RETCPX(U)
...

---------------------------------------------------------

struct complex {float r, i; };
struct complex retcpx_(struct complex *w )
{
    struct complex temp;
    temp.r = w->r + 1.0;
    temp.ii = w->i + 1.0;
    return (temp);
}

C calls Fortran  


struct complex { float r, i; };
struct complex c1, c2;
struct complex *u=&c1;
extern struct complex retfpx_(struct complex *);
  u -> r = 7.0;
  u -> i = -8.0;
  retfpx_( u );
...

---------------------------------------------------------

COMPLEX FUNCTION RETFPX(Z)
  COMPLEX Z
  RETFPX = Z + (1.0, 1.0)
  RETURN
END

11.5.3 Returning a CHARACTER String

Passing strings between C and Fortran routines is not encouraged. However, a Fortran character-string-valued function is equivalent to a C function with two additional first arguments—data address and string length. The general pattern for the Fortran function and its corresponding C function is:

Fortran function  

C function  

CHARACTER*n FUNCTION C(a1, ..., an)


 
void c_ (result, length, a1, ..., an)
char result[ ];
long length;

Here is an example:

Table 11–15 A Function Returning a CHARACTER String

Fortran calls C  

C calls Fortran  


CHARACTER STRING*16, CSTR*9
STRING = ’ ’
STRING = ’123’ // CSTR(’*’,9)
...

------------------------------

void cstr_( char *p2rslt,
            long rslt_len,
            char *p2arg,
            int *p2n,
            long arg_len )
{ /* return n copies of arg */
  int count, i;
  char *cp;
  count = *p2n;
  cp = p2rslt;
  for (i=0; i<count; i++) {
    *cp++ = *p2arg ;
  }
}

void fstr_( char *, long,
           char *, int *, long );
char sbf[9] = "123456789";
char *p2rslt = sbf;
int rslt_len = sizeof(sbf);
char ch = ’*’;
int n = 4;
int ch_len = sizeof(ch);
/* make n copies of ch in sbf
*/
fstr_( p2rslt, rslt_len,
       &ch, &n, ch_len );
...

------------------------------

FUNCTION FSTR( C, N)
  CHARACTER FSTR*(*), C
  FSTR = ’’
  DO I = 1,N
    FSTR(I:I) = C
  END DO
  FSTR(N+1:N+1) = CHAR(0)
END

In this example, the C function and calling C routine must accommodate two initial extra arguments (a pointer to the result string and the length of the string) and one additional argument at the end of the list (length of character argument). Note that in the Fortran routine called from C, it is necessary to explicitly add a final null character. Fortran strings are not null-terminated by default.

11.6 Labeled COMMON

Fortran labeled COMMON can be emulated in C by using a global struct.

Table 11–16 Emulating Labeled COMMON

Fortran COMMON Definition  

C "COMMON" Definition  


COMMON /BLOCK/ ALPHA,NUM
...

extern struct block {
  float alpha;
  int num;
};
extern struct block block_ ;
main ()
{
...
  block_.alpha = 32.;
  block_.num += 1;
...
}

Note that the external name established by the C routine must end in an underscore to link with the block created by the Fortran program. Note also that the C directive #pragma pack may be needed to get the same padding as with Fortran.

f95 aligns data in common blocks to at most 4-byte boundaries by default. To obtain the natural alignment for all data elements inside a common block and match the default structure alignment, use -aligncommon=16 when compiling the Fortran routines.

11.7 Sharing I/O Between Fortran and C

Mixing Fortran I/O with C I/O (issuing I/O calls from both C and Fortran routines) is not recommended. It is better to do all Fortran I/O or all C I/O, not both.

The Fortran I/O library is implemented largely on top of the C standard I/O library. Every open unit in a Fortran program has an associated standard I/O file structure. For the stdin, stdout, and stderr streams, the file structure need not be explicitly referenced, so it is possible to share them.

If a Fortran main program calls C to do I/O, the Fortran I/O library must be initialized at program startup to connect units 0, 5, and 6 to stderr, stdin, and stdout, respectively. The C function must take the Fortran I/O environment into consideration to perform I/O on open file descriptors.

Remember: even though the main program is in C, you should link with f95.

11.8 Alternate Returns

Fortran 77’s alternate returns mechanism is obsolete and should not be used if portability is an issue. There is no equivalent in C to alternate returns, so the only concern would be for a C routine calling a Fortran routine with alternate returns. Fortran 95 will accept Fortran 77 alternate returns, but its use should be discouraged.

The implementation returns the int value of the expression on the RETURN statement. This is implementation dependent and its use should be avoided.

Table 11–17 Alternate Returns

C calls Fortran  

Running the Example  


int altret_ ( int * );
main ()
{
  int k, m ;
  k =0;
  m = altret_( &k ) ;
  printf( "%d %d\n", k, m);
}

------------------------------

SUBROUTINE ALTRET( I, *, *)
  INTEGER I
  I = I + 1
  IF(I .EQ. 0) RETURN 1
  IF(I .GT. 0) RETURN 2
  RETURN
END

demo% cc -c tst.c
demo% f95 -o alt alt.f tst.o
alt.f:
altret:
demo% alt
1 2

The C routine receives the return value 2 from the Fortran routine because it executed the RETURN 2 statement.

11.9 Fortran 2003 Interoperability With C

The Fortran 2003 draft standard (available from http://www.j3-fortran.org) provides a means of referencing procedures and global variables defined by the C programming language from within a Fortran 95 program. And, conversely, provides a means for defining Fortran subprograms or global variables so that they can be referenced from C procedures.

By design, use of these features to accomplish interoperability between Fortran 95 and C programs insures portability across standards-conforming platforms.

Fortran 2003 provides the BIND attribute for derived types, and the ISO_C_BINDING intrinsic module. The module makes accessible to the Fortran program certain named constants, derived types, and procedures that support specification of interoperable objects. The details can be found in the Fortran 2003 standard.