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.
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:
Integer types in Fortran are always signed. In C, integer types may be specified as signed or unsigned, but are unsigned by default.
The values of C_LONG, C_SIZE_T, C_LONG_DOUBLE, AND C_LONG_DOUBLE_COMPLEX are different on different platforms.
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.
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.
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
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].
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.
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;
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)) ...
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);