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.