It is possible to build programs using a mixture of C, C++, and Fortran code. There are some pitfalls, however. The details of mixing languages are beyond the scope of this manual, but a few examples are provided here to introduce the general idea.
One major issue for scientific programmers is the structure of multidimensional arrays. C and C++ use row-major format (all elements of a given row are stored contiguously in memory), while Fortran uses column-major format (all elements of a given column are contiguous).
Hence, matrix[row][col]
in C or C++
is represented as matrix(col,row)
in
Fortran.
This is just one of many differences in how data structures differ between C/C++, and Fortran. More information can be found on the web by searching for "mixing C and Fortran".
Fortran compilers typically decorate
or mangle symbol names with the
program by appending an underscore character. Hence,
a Fortran function called invert()
would
be called as invert_()
from within a C
or C++ program.
Calling C functions from within a Fortran or C++ program doesn't generally require and special effort. Hence, it is often easier to use the Fortran or C++ compiler for the link phase when building a mixed-language program that calls C functions.
This could, however, result in "undefined symbol"
errors, since a Fortran compiler will not search
the standard C libraries by default. If calling standard
C library functions from a Fortran program, you may
need to add -lc
to the link command,
so that the Fortran linker will search the standard
C library, libc.so
.
The example makefiles below show how to build programs with various mixtures of C, C++, and Fortran. If you are not familiar with makefiles, you may want to read Chapter 22, Building with Make first.
BIN = program OBJS = main.o functions.o # Use the same tool chain for all builds to avoid issues CC = gcc CFLAGS = -Wall -O -g FC = gfortran FFLAGS = ${CFLAGS} # Use Fortran compiler to link to avoid name mangling issues LD = ${FC} LDFLAGS = -lc # Link program: main.o functions.o ${LD} -o ${BIN} ${OBJS} ${LDFLAGS} main.o: main.f90 ${FC} -c ${FFLAGS} main.f90 functions.o: functions.c ${CC} -c ${CFLAGS} functions.c
If calling C++ library functions from Fortran built with gfortran, link with -lstdc++ (the GNU C++ library).
BIN = program OBJS = main.o functions.o # Use the same tool chain for all builds to avoid issues CXX = g++ CXXFLAGS = -Wall -O -g FC = gfortran FFLAGS = ${CXXFLAGS} # Use Fortran compiler to link to avoid name mangling issues LD = ${FC} LDFLAGS = -lstdc++ # Link program: main.o functions.o ${LD} -o ${BIN} ${OBJS} ${LDFLAGS} main.o: main.f90 ${FC} -c ${FFLAGS} main.f90 functions.o: functions.cc ${CXX} -c ${CXXFLAGS} functions.cc
If calling Fortran library functions from C or C++ with the GNU compiler collection, add -lgfortran.
BIN = program OBJS = main.o functions.o # Use the same tool chain for all builds to avoid issues CC = gcc CFLAGS = -Wall -O -g FC = gfortran FFLAGS = ${CFLAGS} # Use C compiler to link, since the main program is in C LD = ${CC} LDFLAGS = -lgfortran # Link program: main.o functions.o ${LD} -o ${BIN} ${OBJS} ${LDFLAGS} main.o: main.c ${CC} -c ${CFLAGS} main.c functions.o: functions.f90 ${FC} -c ${FFLAGS} functions.f90
If calling C++ library functions from Fortran built with gfortran, link with -lstdc++ (the GNU C++ library).
BIN = program OBJS = main.o functions.o # Use the same tool chain for all builds to avoid issues CXX = g++ CXXFLAGS = -Wall -O -g FC = gfortran FFLAGS = ${CXXFLAGS} # Use Fortran compiler to link to avoid name mangling issues LD = ${FC} LDFLAGS = -lstdc++ # Link program: main.o functions.o ${FC} -o ${BIN} ${OBJS} ${LDFLAGS} main.o: main.f90 ${FC} -c ${FFLAGS} main.f90 functions.o: functions.cc ${CXX} -c ${CXXFLAGS} functions.cc
Can we mix C, C++, and Fortran source code in the same makefile? Explain.