Navigation: Previous Up Next
11.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.
11.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.
11.1.2
Initialisation and Termination
If the main program is not written in Fortran then either the
initialisation routine
f90_init(int argc,char*argv[])
or the i/o initialisation routine
f90_io_init(void)
should be called from C.
The f90_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
f90_finish(int status) or alternatively f90_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).
11.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).
11.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 | single | Real |
| double | Double |
| double-double | DDReal |
| quadruple | QReal |
| | |
COMPLEX | 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).
11.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.
11.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.
11.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.
11.1.5
SUBROUTINE return types
11.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.
11.1.5.2
SUBROUTINEs with no label arguments
Return type is void.
11.1.6
FUNCTION return types
11.1.6.1
Scalar
-
INTEGER, LOGICAL and REAL.
The intrinsic type as listed above.
-
COMPLEX, -compatible option not used, and not Windows 64-bit mode.
Complex or DComplex according to the precision.
-
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).
-
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).
-
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.
-
Derived type.
The derived-type struct.
11.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.
-
INTEGER, LOGICAL, REAL and COMPLEX.
A pointer to the appropriate intrinsic type (e.g., Complex*).
-
CHARACTER
Return type is Substring, Substring2 or Substring4.
-
Derived type.
A pointer to the derived-type struct.
11.1.6.3
Array non-POINTER functions
-
Intrinsic types.
The appropriate ArrayTemp_ struct for the intrinsic type, as described
above.
-
Derived types.
ArrayTemp_Derived is returned with the len component set to the
size of the derived-type struct.
11.1.6.4
Array POINTER functions
-
CLASS(*)
CSDope1, CSDope2, ... or CSDope7, depending on the rank of
the array.
-
CLASS(derived-type-name)
NPDope1, NPDope2, ... or NPDope7, depending on the rank of
the array.
-
Non-polymorphic non-CHARACTER type.
Dope1, Dope2, ... or Dope7, depending on the rank of the
array.
-
CHARACTER.
ChDope1, ChDope2, ... or ChDope7, depending on the rank of
the array.
Note that non-polymorphic derived-type arrays are returned as DopeN
structs.
11.1.7
Argument types
11.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.
11.1.7.2
non-POINTER non-ALLOCATABLE Scalar
-
non-CHARACTER type.
The address of the argument is passed (e.g., Integer* for an
INTEGER argument).
-
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.
11.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).
11.1.7.4
non-POINTER Array
-
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.
-
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.
11.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.
11.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.
11.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).