Navigation: Previous   Up   Next

9.5 C interoperability [mostly 5.1]

9.5.1 The ISO_C_BINDING module

The intrinsic module ISO_C_BINDING contains The kind parameters

The kind parameter names are for using with the corresponding Fortran types; for example, INTEGER for integral types and REAL for floating-point types. This is shown in the table below. Note that only c_int is guaranteed to be available; if there is no compatible type the value will be negative.

C type Fortran type and kind
_Bool LOGICAL(c_bool)
char CHARACTER(c_char) — For characters as text.
double REAL(c_double)
double _Complex COMPLEX(c_double_complex) or COMPLEX(c_double)
float REAL(c_float)
float _Complex COMPLEX(c_float_complex) or COMPLEX(c_float)
int INTEGER(c_int)
int16_t INTEGER(c_int16_t)
int32_t INTEGER(c_int32_t)
int64_t INTEGER(c_int64_t)
int8_t INTEGER(c_int8_t)
int_fast16_t INTEGER(c_int_fast16_t)
int_fast32_t INTEGER(c_int_fast32_t)
int_fast64_t INTEGER(c_int_fast64_t)
int_fast8_t INTEGER(c_int_fast8_t)
int_least16_t INTEGER(c_int_least16_t)
int_least32_t INTEGER(c_int_least32_t)
int_least64_t INTEGER(c_int_least64_t)
int_least8_t INTEGER(c_int_least8_t)
intmax_t INTEGER(c_intmax_t)
intptr_t INTEGER(c_intptr_t)
long INTEGER(c_long)
long double REAL(c_long_double)
long double _Complex COMPLEX(c_long_double_complex) or COMPLEX(c_long_double)
long long INTEGER(c_long_long)
short INTEGER(c_short)
signed char INTEGER(c_signed_char) — For characters as integers.
size_t INTEGER(c_size_t) Using C_PTR and C_FUNPTR

These are derived type names, so you use them as Type(c_ptr) and Type(c_funptr). Type(c_ptr) is essentially equivalent to the C void *; i.e. it can contain any object pointer. Type(c_funptr) does the same thing for function pointers.

For C arguments like ‘int *’, you don't need to use Type(c_ptr), you can just use a normal dummy argument (in this case of type Integer(c_int)) without the VALUE attribute. However, for more complicated pointer arguments such as pointer to pointer, or for variables or components that are pointers, you need to use Type(c_ptr).

Null pointer constants of both Type(c_ptr) and Type(c_funptr) are provided: these are named C_NULL_PTR and C_NULL_FUNPTR respectively.

To create a Type(c_ptr) value, the function C_LOC(X) is used on a Fortran object X (and X must have the TARGET attribute). Furthermore, the Fortran object cannot be polymorphic, a zero-sized array, an assumed-size array, or an array pointer. To create a Type(c_funptr) value, the function C_FUNLOC is used on a procedure; this procedure must have the BIND(C) attribute.

To test whether a Type(c_ptr) or Type(c_funptr) is null, the C_ASSOCIATED(C_PTR_1) function can be used; it returns .TRUE. if and only if C_PTR_1 is not null. Two Type(c_ptr) or two Type(c_funptr) values can be compared using C_ASSOCIATED(C_PTR_1,C_PTR_2) function; it returns .TRUE. if and only if C_PTR_1 contains the same C address as C_PTR_2.

The subroutine C_F_POINTER(CPTR,FPTR) converts the TYPE(C_PTR) value CPTR to the scalar Fortran pointer FPTR; the latter can have any type (including non-interoperable types) but must not be polymorphic. The subroutine C_F_POINTER(CPTR,FPTR,SHAPE) converts a TYPE(C_PTR) value into the Fortran array pointer FPTR, where SHAPE is an integer array of rank 1, with the same number of elements as the rank of FPTR; the lower bounds of the resultant FPTR will all be 1.

The subroutine C_F_PROCPOINTER(CPTR,FPTR) is provided. This converts the TYPE(C_FUNPTR) CPTR to the Fortran procedure pointer FPTR.

Note that in all the conversion cases it is up to the programmer to use the correct type and other information.

9.5.2 BIND(C) types

Derived types corresponding to C struct types can be created by giving the type the BIND(C) attribute, e.g.
  TYPE,BIND(C) :: mytype
The components of a BIND(C) type must have types corresponding to C types, and cannot be pointers or allocatables. Furthermore, a BIND(C) type cannot be a SEQUENCE type (it already acts like a SEQUENCE type), cannot have type-bound procedures, cannot have final procedures, and cannot be extended.

9.5.3 BIND(C) variables

Access to C global variables is provided by giving the Fortran variable the BIND(C) attribute. Such a variable can only be declared in a module, and cannot be in a COMMON block. By default, the C name of the variable is the Fortran name converted to all lowercase characters; a different name may be specified with the NAME= clause, e.g.
  INTEGER,BIND(C,NAME="StrangelyCapiTalisedCName") :: x
Within Fortran code, the variable is referred to by its Fortran name, not its C name.

9.5.4 BIND(C) procedures

A Fortran procedure that can be called from C can be defined using the BIND(C) attribute on the procedure heading. By default its C name is the Fortran name converted to lowercase; a different name may be specified with the NAME= clause. For example
Again, the C name is for use only from C, the Fortran name is used from Fortran. If the C name is all blanks (or a zero-length string), there is no C name. Such a procedure can still be called from C via a procedure pointer (i.e. by assigning it to a TYPE(C_FUNPTR) variable).

A BIND(C) procedure must be a module procedure or external procedure with an explicit interface; it cannot be an internal procedure or statement function.

A BIND(C) procedure may be a subroutine or a scalar function with a type corresponding to a C type. Each dummy argument must be a variable whose type corresponds to a C type, and cannot be allocatable, assumed-shape, optional or a pointer. If the dummy argument does not have the VALUE attribute, it corresponds to a C dummy argument that is a pointer.

Here is an example of a Fortran procedure together with its reference from C:

SUBROUTINE find_minmax(x,n,max,min) BIND(C,NAME='FindMinMax')
  USE iso_c_binding
  REAL(c_double) x(*),max,min
  INTEGER(c_int),VALUE :: n
  INTRINSIC maxval,minval
  max = MAXVAL(x(:n))
  min = MINVAL(x(:n))

extern void FindMinMax(double *x,int n,double *maxval,double *minval);
double x[100],xmax,xmin;
int n;

This also allows C procedures to be called from Fortran, by describing the C procedure to be called in an interface block. Here is an example:

/* This is the prototype for a C library function from 4.3BSD. */
int getloadavg(double loadavg[],int nelem);

PROGRAM show_loadavg
  USE iso_c_binding
    FUNCTION getloadavg(loadavg,nelem) BIND(C)
      IMPORT c_double,c_int
      REAL(c_double) loadavg(*)
      INTEGER(c_int),VALUE :: nelem
      INTEGER(c_int) getloadavg
  REAL(c_double) averages(3)
  IF (getloadavg(averages,3)/=3) THEN
    PRINT *,'Unexpected error'
    PRINT *,'Load averages:',averages

9.5.5 Enumerations

An enumeration defines a set of integer constants of the same kind, and is equivalent to the C enum declaration. For example,
    ENUMERATOR :: open_door=4, close_door=17
    ENUMERATOR :: lock_door
is equivalent to
  enum {
    open_door=4, close_door=17, lock_door
If a value is not given for one of the enumerators, it will be one greater than the previous value (or zero if it is the first enumerator in the list). The kind used for a particular set of enumerators can be discovered by using the KIND intrinsic on one of the enumerators.

Note that the BIND(C) clause is required; the standard only defines enumerations for interoperating with C.