Using Fortran Subroutines from C++

A compiler converts a code to an object file and then a linker links different object files with each other. As a result, it is possible to mix programming languages in one project. What is just necessary is to know conventions accepted in different programming languages. Below there is a short description on how one can call a Fortran 77 subroutine from C++. This could be useful, as there is a lot of code for numerical methods in Fortran 77.

The sample code is in fortran.tar.tz or you can browse it here.

File sub.f contains a Fortran 77 subroutine that takes different parameters and prints them. File call.cpp is the code in C++ that calls the Fortran subroutine. With gcc, the code could be compiled with the next command

$ g++ call.cpp sub.f -o call.exe -lg2c

gcc recognizes programming language by the file extension and then calls an appropriate compiler. I use gcc 3.4.4 and it calls g77 for Fortran. g77 uses the library libg2c.a and it is not linked by default by g++, so it is necessary to specify it is explicitly. Use -v to see actual commands that have been made by gcc.

Some problem is that a few things are be different for different Fortran 77 compilers and it might be necessary to modify my C++ code. Let us go through call.cpp and I will make comments on where you can expect problems.

1) Function name to call

It happens that the name of a function in the object file is different from the name in the code. C compiler always adds an underscore in front and a function foo becomes always _foo in the object file. C++ compiler mangles the function name and the mangling scheme is not standardized. This is one reason why it is difficult to mix object files from different C++ compilers. For Fortran 77 names there is no standard but the situation is much simpler as for C++, there are just few options. A Fortran compiler also adds an underscore in front of the name but usually it adds another underscore behind. This is default for g77 and you can find underscore at the end of the function name in my C++ code. As we do not want C++ compiler to mangle this function name, we need to specify extern "C" bindings.

What else can one expect? No underscore at the end of the name. A function name written in uppercase. Something like this. Note that this behavior can be influenced by the compiler flags. For example, for g77 they are -fno-underscoring and -fcase-upper. The simplest way to troubleshoot this problem is to employ nm:

$ g77 -c sub.f

$ nm sub.o

and you see what the name is written in the object file. Then it will be necessary to modify the name in the C++ code accordingly.

2) Calling convention for numerical values

Fortran expects all arguments passed by reference. This means that we need to use pointers in C++ – see the declaration for the Fortran function in the C++ code. When one calls the function for array this is already the case, for variables use & operator.

I would say that this is the simplest thing, it is necessary just to check if the type size is the same in C++ and Fortran.

3) Calling convention for characters

This could be a reason for a crash while calling Fortran from another programming language Fortunately the characters are used not often in the numerical code, but occasionally you need to pass them. The problem is that in Fortran 77 one does not use null terminated strings but rather during the call one passes two arguments, the pointer to char* and additionally the length of the char. Moreover, the position of these two arguments is not standardized. They can follow each other (for example in Compaq Visual Fortran) or the length of the string stays at the end of the parameter list (gcc – see call.cpp).

If you need to pass characters to Fortran, a good idea is to check the documentations. Alternatively one can read the assembly code generated by a compiler. Or just make a simple test and find it experimentally.

More Information

Make a search in Google for Using Fortran Subroutines from C++ and you will see many resources to this end.

f2c converts Fortran 77 to C. It can be a solution when you do not have a Fortran compiler at hand. However, the use of a Fortran compiler can produce more efficient code.


Comments are closed.