12.1 Mixing Fortran and C

When mixing Fortran source code with C source code, without using the C interoperability features of Fortran 2003, the following points should be noted.

12.1.1 Naming Conventions

External procedure names and common block names are in lower case with an underscore appended (this is the same as the standard UNIX f77). The main program-unit is called ‘main’.

Module variables and module procedure names are formed by taking the module name (in lower case), appending ‘_MP_’ and then appending the entity's name (in lower case).

These conventions differ when the -compatible option is used. On Windows this causes external procedures and common blocks to be in upper case with no trailing underscore, while module entities have the module name in upper case instead of lower case (64-bit Windows is always -compatible). On most other platforms this option adds an extra underscore (after the one that is always added) for names that already had an underscore.

12.1.2 Initialisation and Termination

If the main program is not written in Fortran then either the initialisation routine
    __NAGf90_rts_init(int argc,char*argv[])
or the i/o initialisation routine
    __NAGf90_io_init(void)
should be called from C. The __NAGf90_rts_init routine initialises the Fortran floating-point environment as well as allowing command-line arguments to be accessed via the Fortran 2003 intrinsic functions and also via the F90_UNIX module. Additionally, the program should be terminated with __NAGf90_finish(int status), or alternatively __NAGf90_io_finish(void) may be called before the usual C termination routine to close all Fortran files and flush the Fortran i/o buffers (failing to do this might corrupt an output file that is still open).

12.1.3 Calling Conventions

The following sections describe in detail the calling conventions used by Fortran programs compiled with the NAG Fortran Compiler in C terms. This information is thus mostly useful to those wishing to mix Fortran and C code.

The conventions used for the Fortran 77 subset of Modern Fortran are compatible with the de facto UNIX f77 conventions (except for COMPLEX functions compiled without the -compatible option).

12.1.4 Data Types

Definitions of data types useful in communicating from C to Fortran are in the files dope.h and nagfortran.h, which are located in the compiler library directory (usually /usr/local/lib/NAG_Fortran on UNIX-like systems).

Fortran Data Type Fortran Precision C typedef name
INTEGER 8 bits Integer1
16 bits Integer2
32 bits Integer or Integer3
64 bits Integer4
LOGICAL 8 bits Logical1
16 bits Logical2
32 bits Logical
64 bits Logical4
REAL half __NAGf90_HReal
single Real
double Double
double-double DDReal
quadruple QReal
COMPLEX half __NAGf90_HComplex
single Complex
double DComplex
double-double DDComplex
quadruple QComplex

Note that DDReal and QReal are the same on most systems; on Sun Solaris these are different (the latter being an IEEE-conformant 128-bit floating-point type).

12.1.4.1 Pointers

Scalar non-polymorphic non-CHARACTER POINTER types are simply C pointers to the object.

An array POINTER is a dope vector describing the array pointed to. Unlike a simple address, these dope vectors are capable of directly describing non-contiguous array sections of contiguous arrays. See below (DopeN and ChDopeN) for further details. Polymorphic dope vectors are NPDopeN except for CLASS(*) pointers which are CSDopeN.

12.1.4.2 Derived types

Fortran derived types are translated into C structs. If BIND(C) or SEQUENCE is used, the order of the items within the struct is the same as the order within the derived type definition. Otherwise, the order of items is permuted to put larger types at the front of the struct so as to improve alignment and reduce storage; the C output code can be inspected to determine the ordering used.

12.1.4.3 Supporting types

Char
unsigned char
Data type for default (single-byte) character storage.
Char2
unsigned short
Data type for 16-bit (JIS and UCS-2) character storage.
Char4
unsigned int
Data type for 32-bit (UCS-4) character storage.
Substring
struct { Char *addr; Chrlen len;}
Describes a single-byte (default) CHARACTER string; used for deferred-length default CHARACTER variables and as the return type of variable-length scalar non-POINTER default CHARACTER functions and all POINTER default CHARACTER functions.
Substring2
struct { Char2 *addr; Chrlen len;}
Describes a 16-bit (JIS or UCS-2) CHARACTER string; used for deferred-length 16-bit CHARACTER variables and as the return type of variable-length scalar non-POINTER 16-bit CHARACTER functions and all POINTER 16-bit CHARACTER functions.
Substring4
struct { Char4 *addr; Chrlen len;}
Describes a 32-bit ISO_10646 (UCS-4) CHARACTER string; used for deferred-length 32-bit CHARACTER variables and as the return type of variable-length scalar non-POINTER UCS-4 CHARACTER functions and all POINTER UCS-4 CHARACTER functions.
Offset
int, long or long long
An integer type for addressing and subscript calculations; this is int (32-bit) on 32-bit systems and small model 64-bit systems, and a 64-bit integer type on large model 64-bit systems.
Chrlen
usually int, or long long on 64-bit Windows.
An integer type for representing character length.
Pointer
usually char *.
A byte pointer used to refer to any type and for pointer arithmetic.
Triplet
struct { Offset extent,mult,lower;}
Contains the parameters of an array dimension. extent is the size of that dimension, mult is the stride (i.e., the distance between successive elements in bytes) and lower is the lower bound. It is a component of the DopeN and ChDopeN structs.
DopeN
struct { Pointer addr; Offset offset; Triplet dim[N];}
Dope vectors for all non-polymorphic non-CHARACTER arrays (including arrays of derived type). N is the rank and is from 1 to 7. addr is the address of the first element, dim describes each dimension and offset is the offset to add to the subscript calculation, i.e., SUM(mult*lower). This is used as the return type for POINTER array functions; a pointer to it is used as the argument type for assumed-shape and POINTER array arguments.

An array pointer which has been nullified has an addr field which is a null pointer; note that zero-sized arrays have an addr field which is not a null pointer.

ChDopeN
struct { Pointer addr; Chrlen len; Offset offset; Triplet dim[N];}
These are exactly the same as the DopeN structs with the addition of the len component which specifies the CHARACTER length.
ArrayTemp_type
struct { type *addr; Offset extent[7];}
Describes a contiguous array of type, which is one of: Integer1, Integer2, Integer, Integer4, Logical1, Logical2, Logical, Logical4, Real, Double, QReal, Complex, DComplex or QComplex. It is used as the return type for non-POINTER array functions. Note that extent values after the rank of the array being described are undefined.
ArrayTemp_Character
struct { Char *addr; Chrlen len; Offset extent[7];}
Describes a contiguous CHARACTER array; it is the same as the other array types with the addition of the len component for the CHARACTER length.
ArrayTemp_Derived
synonym for ArrayTemp_Character.
Describes a contiguous array of any derived type. The len field in this case is the size of the derived type array element.

12.1.5 SUBROUTINE return types

12.1.5.1 SUBROUTINEs with label arguments

The return type is int; its value is the index of the label to which control is to be transferred (1 for the first label, etc.). Zero or an out-of-range value indicates no control transfer is to take place.

12.1.5.2 SUBROUTINEs with no label arguments

Return type is void.

12.1.6 FUNCTION return types

12.1.6.1 Scalar

  1. INTEGER, LOGICAL and REAL.
    The intrinsic type as listed above.
  2. COMPLEX, -compatible option not used, and not Windows 64-bit mode.
    Complex or DComplex according to the precision.
  3. COMPLEX, -compatible option used, or Windows 64-bit mode.
    Return type is void. The address of a temporary of type Complex or DComplex is passed as the initial argument of the function (the result is written to this location).
  4. CHARACTER with fixed or assumed length.
    Return type is void. Two additional initial arguments are passed to the function, the first (Char*, Char2* or Char4*) being the address to which the result is to be written and the second (Chrlen) being the length of the result (in case the called function is of assumed length).
  5. CHARACTER with variable length.
    Return type is Substring, Substring2 or Substring4 (described above). The called function allocates the storage for the string being returned; it is the caller's responsibility to deallocate it when it is no longer required.
  6. Derived type.
    The derived-type struct.

12.1.6.2 Scalar POINTER functions

Note that with all POINTER-valued functions the storage to which the result points may have been allocated within the called function or the result may point to pre-existing storage.
  1. INTEGER, LOGICAL, REAL and COMPLEX.
    A pointer to the appropriate intrinsic type (e.g., Complex*).
  2. CHARACTER
    Return type is Substring, Substring2 or Substring4.
  3. Derived type.
    A pointer to the derived-type struct.

12.1.6.3 Array non-POINTER functions

  1. Intrinsic types.
    The appropriate ArrayTemp_ struct for the intrinsic type, as described above.
  2. Derived types.
    ArrayTemp_Derived is returned with the len component set to the size of the derived-type struct.

12.1.6.4 Array POINTER functions

  1. CLASS(*)
    CSDope1, CSDope2, ... or CSDope7, depending on the rank of the array.
  2. CLASS(derived-type-name) NPDope1, NPDope2, ... or NPDope7, depending on the rank of the array.
  3. Non-polymorphic non-CHARACTER type.
    Dope1, Dope2, ... or Dope7, depending on the rank of the array.
  4. CHARACTER.
    ChDope1, ChDope2, ... or ChDope7, depending on the rank of the array.

Note that non-polymorphic derived-type arrays are returned as DopeN structs.

12.1.7 Argument types

12.1.7.1 CHARACTER type

All normal arguments of CHARACTER type, whether default CHARACTER or multi-byte CHARACTER, have an additional Chrlen argument being the length of the CHARACTER entity; this additional argument is passed at the end of the argument list after all the normal arguments. When there are several CHARACTER arguments their lengths are passed in order from left to right.

This is except on 32-bit Windows when the -compatible option is specified, the additional argument immediately follows the CHARACTER argument.

The other exception to this rule is for assumed-shape CHARACTER arrays; in this case the length of the dummy argument is taken directly from the field in the dope vector and is not passed separately.

12.1.7.2 non-POINTER non-ALLOCATABLE Scalar

  1. non-CHARACTER type.
    The address of the argument is passed (e.g., Integer* for an INTEGER argument).
  2. CHARACTER.
    The address of the argument is passed, and additionally the length of the argument is passed as a separate Chrlen argument at the end of the argument list.

12.1.7.3 POINTER and ALLOCATABLE Scalar

These are passed exactly the same as the normal case except that the address of the pointer (or allocatable descriptor) is passed (e.g., Integer** for an INTEGER POINTER).

12.1.7.4 non-POINTER Array

  1. Assumed shape.
    The address of an appropriate dope vector describing the array is passed (i.e., a CSDopeN*, NPDopeN*, DopeN* or a ChDopeN*, depending on the polymorphism and type of the dummy argument). There is no need for the array to be contiguous as long as it can be described by an array section.
  2. Other.
    The address of the first element of the array is passed. For CHARACTER arrays the length of each array element is passed as an Chrlen at the end of the argument list, the same as for scalars. The array must be contiguous.

12.1.7.5 POINTER Array

The address of an appropriate dope vector is passed, the same as for assumed-shape arrays. For CHARACTER arrays the length is passed at the end as a separate argument.

12.1.7.6 Procedures

The address of the procedure is passed. CHARACTER functions have the length passed as a separate argument at the end of the list; if the function is of variable length this length will be negative.

12.1.7.7 OPTIONAL arguments

If an OPTIONAL argument is .NOT.PRESENT() a null pointer of the appropriate type is passed (e.g., for an INTEGER scalar, an (Integer*)0 is passed).