home

How to Link Fortran and C/C++

On this document, I explain how to link C/C++ code with program written in Fortran.

Introduction

The document is devided into sections each treating an issue that you may encounter when you link C and Fortran. I shall use as an example a function defined in fortran. We wish to call this function from C++. The function definition in Fortran is:
 subroutine gagafe(n, r, f, u, ax, ay, az)
integer ncoord
real*8 r(n), f(n), u, ax, ay, az
...
end
In C++ the function defined in Fortran is declared as:
 extern "C" void gagafe_(int const * n, double const * r, double* f, double* u, double const * ax, double const * ay, double const * az);

Matching Types

The first thing to do is to find matching types between the two languages. On the computers I use for example (macintosh PowerPC and Linux x86) integer is 4 bytes long and corresponds in C to int or long (int and long are the same on those computer). Type real*8 correspond to double in C and is 8 bytes long. The size of a type can be checked in C by using sizeof. Example:
 cout << "sizeof(double) = " << sizeof(double) << endl;
cout << "sizeof(int) = " << sizeof(int) << endl;
On my computer, it returns:
sizeof(double) = 8
sizeof(int) = 4
There is no guarantee that those types will always match as their size may differ on different machines. A way to solve the problem is to use fixed size types. For example Fortran type real*8 has a fixed size of 8 bytes. In C, fixed size integer types are defined in stdint.h. For example, type int32_t is a integer of size 32 bits (or 4 bytes). These types are standard in ISO C99. I did not find any standard fixed size types for floating numbers.
When you have found the matching types, you must declare the Fortran function in the C/C++ code. You may have noticed that the variables are declare as pointers in C++, although they are used like variables in Fortran. Some pointers were declared as pointing to constant data (const keyword).This is only to indicate in the C++ code that those variables are not changed by Fortran function gagafe. They do not actually prevent, the variables from being modified by the fortran code. So be careful.

Matching Function Names

extern "C" in C++

The extern "C" preceding the function is only for C++. There would be nothing in C. This is because the name of the functions once compiled (name of the function in the object file or .o file) is different from the name of the function in the source code. In C and Fortran, those names are similar. But in C++, because C++ allows to overload functions, the names of the compiled functions is the names of the function in the source mixed with something else to indicate the types of the function parameters. Keyword extern "C" indicates that we wish the function to be named like in C. On Unix machines, the command nm can be used to display the content of an object file. For example, I used it on my computer with an object file compiled by g77 :
 shd16:~/water/source phy$ nm gagafetip4p.o \n
... \n
000007f0 S _gagafe_ \n
... \n
_gagafe_ is the name of my function in the object file.

Matching Function Names

You can see on the C++ declaration of gagafe that the function has an underscore appended. This underscore is not always needed. It depends on the name of your function and the compiler you are using. To compile you use the gnu compiler, g++ for C++ and g77 for Fortran. In Fortran, g77 adds two underscores, one at beginning the other at the end of the function (see nm gagafetip4p.o). In C, only one underscore is added at the beginning of the function. The extra underscore in the C++ declaration is to make the functions match. Note that this underscore is not always required. For example, if the function names in the source already contains a underscore the naming for the object works differently. Other compilers may use different naming convention (e.g. xlf does not add any undercore at the end). It also depends on the machine even if you use the same compiler (e.g. gcc). That is why nm is very useful to check the functions names with nm to make the function match. Compilers usually have options to change the naming of the function (e.g. "-fleading-underscore" and "-fno-leading-underscore" for gcc, "-funderscoring" for g77, etc ...). However to make your code more portable, I strongly recommend to use these options as little as you can and instead to dub your functions. For example, in my code I had a function called gagafetip4p written in C that I wanted to call it from Fortran. In the C code I defined another function:
 inline void gagafetip4p_(int const * n, double const * r, double* f, double* u, double const * ax, double const * ay, double const * az)
{
gagafetip4p(n, r, u, ax, ay, az);
}
This way the linker may use either gagafetip4p or gagafetip4p_ depending on the naming convention used by the compilers.

Case

Fortran is case insensitive while C is case sensitive. Fortran compiler converts function names into lower case at compilation. So the functions in C must be lower case. Again you use nm to check the link names.

Libraries

When you use a compiler to link a program, the standard library is automatically added. For example, if we are linking a program written in C++, we can write: g++ -o program file1.o file2.o We do not need add the standard library as it is automatically added: g++ -o program file1.o file2.o -lstdc++ When linking a program written C and Fortran, the standard library of at least one them must be explicitly added. For example, when I link a program compiled with g++ and g77 . I write something like: g++ -o program file1cpp.o file2cpp.o file1fort.o file2fort.o -lg2c When I link program compiled with g++ and xlf. I write something like: g++ -o program file1cpp.o file2cpp.o file1fort.o file2fort.o -L/opt/ibmcmp/xlf/8.1/lib -lxlf90 -lxlfmath -lxl

Common Blocks

It is also possible from C common blocks defined in Fortran. For example, we have the following common block defined in Fortran:
 integer n
real*8 array(3)
common /block/ n, array
In C the common block is declared as a structure.
 struct Block {
int n;
double array[3];
} block_;
The names of Block, n and array do not matter, but the members must have the same order as in the common block and same sizes. The variable name block_ do matter as it is used to link the object. It follows the same rules as functions' names and therefore has the same issues (Matching Function Names, Case). Again, command nm is helpful check link names.
Generated on Wed Aug 15 13:28:06 2007 for Lanczos Saddle Point Searches by  doxygen 1.5.2

home