Evgenii B. Rudnyi, 2008, (c) All rights reserved
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.
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.
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.
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.
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.
Please post your comments, questions, suggestions to the discussion group at http://groups.google.com/group/matrixprogramming.