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);

Submit feedback on this help topic

Copyright © 1996-2010, Intel Corporation. All rights reserved.