Interoperability with C

It is often desirable to have a program which contains both Fortran and C code, and in which routines written in one language are able to call routines written in the other. The Intel® Fortran compiler supports the Fortran 2003 standardized mechanism for allowing Fortran code to reliably communicate (or interoperate) with C code. The following describes interoperability requirements for types, variables, and  procedures.

Interoperability of Intrinsic Types

The intrinsic module ISO_C_BINDING contains named constants that hold kind type parameter values for intrinsic types.

The more commonly used types are included in the following table. The following applies:

Named constant from ISO_C_BINDING
(kind type parameter if value is positive)
C type Equivalent Fortran type
C_SHORT
C_INT
C_LONG
C_LONG_LONG
short int
int
long int
long long int
INTEGER(KIND=2)
INTEGER(KIND=4)
INTEGER (KIND=4 or 8)
INTEGER(KIND=8)
C_SIGNED_CHAR signed char
unsigned char
INTEGER(KIND=1)
C_SIZE_T size_t INTEGER(KIND=4 or 8)
C_INT8_T
C_INT16_T
C_INT32_T
C_INT64_T
int8_t
int16_t
int32_t
int64_t
INTEGER(KIND=1)
INTEGER(KIND=2)
INTEGER(KIND=4)
INTEGER(KIND=8)
C_FLOAT
C_DOUBLE
C_LONG_DOUBLE
float
double
long double
REAL(KIND=4)
REAL(KIND=8)
REAL(KIND=8 or 16)
C_FLOAT_COMPLEX
C_DOUBLE_COMPLEX
C_LONG_DOUBLE_COMPLEX
float _Complex
double _Complex
long double _Complex
COMPLEX(KIND=4)
COMPLEX(KIND=8)
COMPLEX(KIND=8 or 16)
C_BOOL _Bool LOGICAL(KIND=1)
C_CHAR char CHARACTER(LEN=1)

While there are named constants for all possible C types, every type is not necessarily supported on every processor. Lack of support is indicated by a negative value for the constant in the module.

For a character type to be interoperable, you must either omit the length type parameter or specify it using an initialization expression whose value is one.

Interoperability with C Pointers

For interoperating with C pointers, the module ISO_C_BINDING contains the derived types C_PTR  and C_FUNPTR, which are interoperable with C object and function type pointers, respectively.

These types, as well as certain procedures in the module, provide the mechanism for passing dynamic arrays between the two languages. Because its elements need not be contiguous in memory, a Fortran pointer target or assumed-shape array cannot be passed to C. However, you can pass an allocated allocatable array to C, and you can associate an array allocated in C with a Fortran pointer.

Interoperability of Derived Types

For a derived type to be interoperable with C, you must specify the BIND(C) attribute:

TYPE, BIND(C) :: MYTYPE

Additionally, as shown in the examples that follow, each component must have an interoperable type and interoperable type parameters, must not be a pointer, and must not be allocatable. This allows Fortran and C types to correspond.

typedef struct {
int m, n;
float r;
} myctype

The above is interoperable with the following:

USE, INTRINSIC :: ISO_C_BINDING
TYPE, BIND(C) :: MYFTYPE
INTEGER(C_INT) :: I, J
REAL(C_FLOAT) :: S
END TYPE MYFTYPE

Interoperability of Variables

A scalar Fortran variable is interoperable if its type and type parameters are interoperable and it is not a pointer.

An array Fortran variable is interoperable if its type and type parameters are interoperable and it has an explicit shape or assumed size. It interoperates with a C array of the same type, type parameters, and shape, but with subscripts reversed.

For example, a Fortran array declared as INTEGER :: A(18, 3:7, *) is interoperable with a C array declared as int b[][5][18].

Interoperability of Procedures

For a procedure to be interoperable, it must have an explicit interface and be declared with the BIND attribute, as shown in the following:

FUNCTION FUNC(I, J, K, L, M), BIND(C)

In the case of a function, the result must be scalar and interoperable.

A procedure has an associated binding label, which is global in scope. This label is the name by which the C processor knows it and is, by default, the lower-case version of the Fortran name. For example, the above function has the binding label func. You can specify an alternative binding label as follows:

FUNCTION FUNC(I, J, K, L, M), BIND(C, NAME=’myC_Func’)

All dummy arguments must be interoperable. Furthermore, you must ensure that either the Fortran routine uses the VALUE attribute for scalar dummy arguments, or that the C routine receives these scalar arguments as pointers to the scalar values.  Consider the following call to this C function:

intc_func(int x, int *y);

As shown here, the interface for the Fortran call to c_func must have x passed with the VALUE attribute, but y should not have the VALUE attribute, since it is received as a pointer:

INTERFACE
INTEGER (C_INT) FUNCTION C_FUNC(X, Y) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
INTEGER (C_INT), VALUE :: X
INTEGER (C_INT) :: Y
END FUNCTION C_FUNC
END INTERFACE

Alternatively, the declaration for y can be specified as a C_PTR passed by value:

TYPE (C_PTR), VALUE :: Y

To pass a scalar Fortran variable of type character, the character length must be one.

Interoperability of Global Data

A module variable or a common block can interoperate with a C global variable if the Fortran entity uses the BIND attribute and the members of that entity are also interoperable.  For example, consider the entities C_EXTERN, C2, COM and SINGLE in the following module:

MODULE LINK_TO_C_VARS
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT), BIND(C) :: C_EXTERN
INTEGER(C_LONG) :: C2
BIND(C, NAME=’myVariable’) :: C2
COMMON /COM/ R,S
REAL(C_FLOAT) :: R,S,T
BIND(C) :: /COM/, /SINGLE/
COMMON /SINGLE/ T
END MODULE LINK_TO_C_VARS

These can interoperate with the following C external variables:

int c_extern;
long myVariable;
struct {float r, s;} com;
float single;

Example of Fortran Calling C

The following example calls a C function.

C Function Prototype:

int C_Library_Function(void* sendbuf, int sendcount, int *recvcounts);

Fortran Modules:

MODULE FTN_C_1
USE, INTRINSIC :: ISO_C_BINDING
END MODULE FTN_C_1

MODULE FTN_C_2
INTERFACE
INTEGER (C_INT) FUNCTION C_LIBRARY_FUNCTION &
(SENDBUF, SENDCOUNT, RECVCOUNTS) &
BIND(C, NAME=’C_Library_Function’)
USE FTN_C_1
IMPLICIT NONE
TYPE (C_PTR), VALUE :: SENDBUF
INTEGER (C_INT), VALUE :: SENDCOUNT
TYPE (C_PTR), VALUE :: RECVCOUNTS
END FUNCTION C_LIBRARY_FUNCTION
END INTERFACE
END MODULE FTN_C_2

Fortran Calling Sequence:

USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT, C_FLOAT, C_LOC
USE FTN_C_2
...
REAL (C_FLOAT), TARGET :: SEND(100)
INTEGER (C_INT) :: SENDCOUNT
INTEGER (C_INT), ALLOCATABLE, TARGET :: RECVCOUNTS(100)
...
ALLOCATE( RECVCOUNTS(100) )
...
CALL C_LIBRARY_FUNCTION(C_LOC(SEND), SENDCOUNT, &
C_LOC(RECVCOUNTS))
...

Example of C Calling Fortran

The following example calls a Fortran subroutine called SIMULATION. This subroutine corresponds to the C void function simulation.

Fortran Code:

SUBROUTINE SIMULATION(ALPHA, BETA, GAMMA, DELTA, ARRAYS) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
INTEGER (C_LONG), VALUE :: ALPHA
REAL (C_DOUBLE), INTENT(INOUT) :: BETA
INTEGER (C_LONG), INTENT(OUT) :: GAMMA
REAL (C_DOUBLE),DIMENSION(*),INTENT(IN) :: DELTA
TYPE, BIND(C) :: PASS
INTEGER (C_INT) :: LENC, LENF
TYPE (C_PTR) :: C, F
END TYPE PASS
TYPE (PASS), INTENT(INOUT) :: ARRAYS
REAL (C_FLOAT), ALLOCATABLE, TARGET, SAVE :: ETA(:)
REAL (C_FLOAT), POINTER :: C_ARRAY(:)
...
! Associate C_ARRAY with an array allocated in C
CALL C_F_POINTER (ARRAYS%C, C_ARRAY, (/ARRAYS%LENC/) )
...
! Allocate an array and make it available in C
ARRAYS%LENF = 100
ALLOCATE (ETA(ARRAYS%LENF))
ARRAYS%F = C_LOC(ETA)
...
END SUBROUTINE SIMULATION

C Struct Declaration

struct pass {int lenc, lenf; float *c, *f;};

C Function Prototype:

void simulation(long alpha, double *beta, long *gamma, double delta[], struct pass *arrays);

C Calling Sequence:

simulation(alpha, &beta, &gamma, delta, &arrays);