NAG Fortran Compiler, Release 7.2: C interoperability [mostly 5.1]

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

- for each C type (e.g. `float`), a named constant for use as a KIND parameter for the corresponding Fortran type,
- types `C_PTR` and `C_FUNPTR` for interoperating with C object pointers and function pointers,
- procedures for manipulating Fortran and C pointers.

#### 9.5.1.1 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)`

#### 9.5.1.2 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

      SUBROUTINE sub() BIND(C,NAME='Sub')
      ...

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

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

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
      INTERFACE
        FUNCTION getloadavg(loadavg,nelem) BIND(C)
          IMPORT c_double,c_int
          REAL(c_double) loadavg(*)
          INTEGER(c_int),VALUE :: nelem
          INTEGER(c_int) getloadavg
        END FUNCTION
      END INTERFACE
      REAL(c_double) averages(3)
      IF (getloadavg(averages,3)/=3) THEN
        PRINT *,'Unexpected error'
      ELSE
        PRINT *,'Load averages:',averages
      END IF
    END

### 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,

      ENUM,BIND(C)
        ENUMERATOR :: open_door=4, close_door=17
        ENUMERATOR :: lock_door
      END ENUM

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.