Personal tools
You are here: Home / openCMISS / Wiki / Issues with Interfaces Between C and Fortran
Navigation
Log in


Forgot your password?
 

Issues with Interfaces Between C and Fortran

A library written (predominantly) in either C or Fortran should be able to provide an API that defines similar interfaces to both C and Fortran.

These comments are relevant to Fortran 95 unless otherwise stated.

Highlights

As long as a library has an API which provides functions to access only simple

scalar data types, and no complex data structures are public, providing an interface between C and Fortran should not be too difficult.

It may be best for a library written in Fortran to avoid defining the procedures that provide its API in Fortran modules because the symbol names generated by the

compiler may not be representable in C.

Simple Scalar Data Objects

Most commonly used floating and fixed point Fortran data types have

equivalent data types in C. (Does Fortran have unsigned types? Is this implementation specific?)

(Are complex Fortran data types equivalent to C99's _Complex?).

The Fortran logical types may be implemented with different binary values

meaning true or false on different platforms (VMS comes to mind), and so there is not necessary a direct equivalent in C. An enum type could probably be used with macros for testing true and false but it would probably be easier to just use integers.

Fortran 2003 provides the 'iso_c_binding' module with named constants for data

type kinds corresponding to C data types.

Passing Arguments by Reference

Fortran is usually implemented so that simple scalar data objects are passed

by reference on invocation of procedures. Objects not passed by reference are character types and assumed-shape arrays, which are both discussed below.

A fortran procedure with arguments of only simple scalar data types can be

called from C but the interface may appear unusual to C as even intent(in) (or const) arguments need to be passed by reference. For many procedures, it would be more elegant to provide a separate C interface through a wrapper layer written in C. This wrapper could be provided by inline functions.

Similarly, it would be possible for a library written in C with arguments of

only simple scalar data types to provide an interface that could be called from Fortran but often a wrapper might be used to provide the Fortran interface.

Fortran 2003 provides the 'value' attribute for scalar dummy arguments for

passing variables by value.

Symbol Names

On most systems fortran symbol names are lower case with trailing

underscores. Sometimes a second underscore is added. AIX no underscore.

If a library provides an interface directly to a Fortran function then it

may be best to provide a preprocessor definition for the procedure name.

The symbol names given by compilers to public procedures in Fortran modules

may not be symbols that can be represented in C. XL compilers on AIX give the symbol a name of the form '__module_name_NMOD_procedure_name', which can be represented in C, but SGI's xlf90 gives symbols names of the form 'PROCEDURE_NAME.in.MODULE_NAME', which cannot be represented in C code. To provide an interface with a symbol name compatible with C a wrapper Fortran procedures that used the module would be required. It is probably easiest to avoid placing procedures that provide the API of a library in Fortran modules.

Fortran is not case sensitive and so the symbol name of a C function cannot

necessarily be specified. A library written in C might use a C wrapper to provide the necessary symbol names, or could be compiled with a different set of preprocessor definitions to create a separate Fortran library, or could always be compiled with the preprocessor definitions of symbol names and make them available through the C api.

A disadvantage of using preprocessor definitions for symbol names is that it

may make debugging more difficult for compilers and debuggers that don't provide information on preprocessor definitions. Perhaps wrapper functions could be used only when compiling for debugging (with preprocessor definition values set to their name).

Fortran 2003 provides the 'bind' attribute for procedures to specify that

they should be interoperable with C and allows a C symbol name to be specified.

Fortran Character Data Objects

Although elements of Fortran character types correspond to the C char type,

there are difficulties in the way Fortran passes these types to procedures.

When character data types of length greater than 1 are passed between

Fortran functions the length is passed as well as the reference to the data. Different implementations of Fortran pass these two pieces of information in different ways.

If the length is equal to 1 then it seems that most implementations still

pass both pieces of information.

Many unix implementations pass the reference in the order of procedure

arguments and the length by value at the end of all the other arguments. This is the easiest implementation to interface with C as the additional length argument can be ignored when passed to a C function, and is not used if passed to a Fortran function that specifies the length explicitly (probably to 1 with an array size that may be a dummy argument).

However other implementations pass the length argument immediately after the

reference to the data (MS Visual Studio) (which is equivalent to passing a structure by value), or pass a structure by reference, or use a descriptor (Cray and VMS). Is a descriptor the same as a structure (reference)?. In these cases platform-dependent wrapper routines (written in C) can provide the required interface.

Fortran functions returning character types are probably best avoided.

Fortran 2003 requires that the length of a character type must be 1 for

interoperability with C. This is not a significant restriction as arrays of characters can still be used (to provide varying length even).

Fortran Pointers and Addresses

A Fortran pointer is typed according to the rank of its target and includes

an address information about whether it has been associated, the dimensions of its target, and stride for indices. C pointers are just addresses.

This makes it difficult for linked data structures to made available from

one language to another. However, it is probably better that such complicated data structure are not made public anyway (so that they can be changed as necessary) and access to the structure components can be provided through functions.

Although Fortran does not have an address type, a large-enough integer type

is probably be available to store an address and would probably be equivalent to a C pointer.

The (reference of the) target of a pointer can be passed to a C function

which could return the address. (Many Fortran compilers provide this through the 'loc' function.) Similarly, a C function (or a Fortran procedure with mismatching arguments) could probably be used to store a dummy procedure address in an integer type.

The Fortran 'size' function can be used to obtain the dimensions of an

object from a Fortran pointer. Is there any way to determine the stride of each index?

Fortran 2003 provides 'c_ptr' and 'c_funptr' derived types for storing

addresses, as well as functions for converting them to and from Fortran pointers. It also provides Fortran procedure pointers.

Arrays

Fortran usually passes arrays by reference when passed as explicit-shape or

assumed-size arrays, so it can pass to C or receive from C a reference to an array. (The assumed shape interface includes address size and stride information and so this won't interface well with C.) Note that if Fortran array pointers and assumed-shape dummy arrays refer to discontiguous data, the compiler needs to implement a copy of the array before and after the function call when passing the array through the explicit-shape or assumed-size interface. The compiler may not even bother to check contiguity and just do the copying.

A C library may be able to use some Fortran code to set up a Fortran pointer

to an array of its data so that the Fortran pointer could be made available to a Fortran client for interpreting (in Fortran) without a function call. This would only work well though if the Fortran implementation passes its pointers by reference (to the pointer).

C arrays are indexed from 0 whereas Fortran arrays are usually indexed from

1. If array indices are passed between languages, it is necessary to clarify from where the index counts.

For multidimensional arrays, remember that the relationship between indices

and storage is different in the two languages. An array declared in Fortran as:

  integer :: a(18, 3:7, *)

is interoperable with a C array declared as::

  int b[][5][18].

I/O

Fortran and C compilers may not both use the same buffers (and XL compilers

on AIX in 2003 and pgf90 5.2 on Linux certainly didn't). Where possible it would be better if each file was only written to by one language at a time. There is no reason why a file couldn't currently be opened read-only more than once, where each instance would be used by a single language.

Sometimes it may be easier for output to a particular file to originate from

more than one language. Standard output and standard error are files where this is likely to happen. In this case, the streams are best flushed before writing changes to another language (or the output may be quite unreadable). Fortran does not provide a command to flush an output stream until Fortran 2003 but some compilers may implement the extension or their own variant.

Memory Allocation

If the library that allocates a block of memory does its deallocation there is no

problem. (If not there may be problems because the fortan compiler may not use malloc and free for memory allocation.)

Interface Definition Language

"Babel":http://www.llnl.gov/CASC/components/babel.html provides wrappers

between Fortran 77, Fortran 90, C, C++, Python, and Java (client only). It is available under LGPL. This may one day also support "Parallel Data Redistribution":http://www.llnl.gov/CASC/components/parallel.html.

It may be worth looking at this code to see how it handles data type translations.

PETSc

"PETSc":http://www-unix.mcs.anl.gov/petsc/petsc-as/index.html provides interfaces for C, C++, Fortran, and Python, so it may be worth seeing how PETSc handles these interfaces.