Sunteți pe pagina 1din 3

Calling Fortran functions from C

Fortran functions that receive numeric variables from C C The Fortran function must be declared at the beginning of the C calling function (e.g. main) like this:
extern void read_(int *small, float *medium, double *large);

Note that we have to pass all variables to Fortran as pointers. Although the function name is not case sensitive in Fortran, it gains an underscore in the C declaration and when it is called:
read_(&small, &medium, &large);

Fortran The Fortran function receives the variables as follows:


SUBROUTINE READ(small,medium,large) INTEGER small REAL medium DOUBLE large

The precise size of these variables depends on your system's architecture (32 bit verses 64 bit), so you need to confirm the correspondence between ints, floats and doubles in C and Fortran on your system. Otherwise, calling a Fortran function from C with numeric variables is straightforward. Fortran functions that receive string variables from C C This is slightly more complicated. The Fortran function must be declared at the beginning of the C calling function (e.g. main) like this:
extern void load_(char *string, size_t *len_string);

Note that we have to pass all variables to Fortran as pointers. Our string variable is already a pointer, but we have to pass the string's length as a pointer too. Although the function name is not case sensitive in Fortran, it gains an underscore in the C declaration and when it is called:
len_string = strlen(string); load_(string, &len_string);

Note that in passing the string from C to Fortran we also need to pass the length of the string, hence the use of strlen beforehand (not forgetting to declare the string length variable as a size_t rather than an int).

Fortran The Fortran function has to be modified to receive a string variable as a byte array (instead of a character string), as well as the string's length:
SUBROUTINE LOAD(string,len_string) BYTE string(51) INTEGER len_string

Note that the original Fortran function would not have needed an integer variable to store the length of the received string. We also have to add the following to our Fortran function so that it copies the byte array to a string:
CHARACTER*50 charstr WRITE (charstr,'(50a)') (string(i),i=1,len_string)

Note that we specify a byte array that is one byte longer than the Fortran character string. This is for the NULL character that C would have placed at the end of the string. Unfortunately, Fortran pads character strings with spaces, so you might want to use the Fortran TRIM function to get rid of them on output, e.g.
WRITE(*,'(a,a)'),"This is the string passed from C: ",TRIM(charstr)

Fortran common block declarations If in your C code you have to reference a variable that is in a Fortran function's common block declaration such as:
IMPLICIT DOUBLE PRECISION YTEMP,SPEC DIMENSION YTEMP(500),SPEC(999) COMMON/YTEMP/ YTEMP,SPEC

you need to declare it outside main as a global struct variable in C like this:
struct { double ytemp[500],spec[999]; } ytemp_;

It should be noted that the use of global variables like this is not good practice (common block declarations are deprecated in Fortran 95), but you may well be stuck with them in the Fortran functions you want to use in your C programme. Compilation and Linking Using the latest versions of gcc and gfortran for compilation and linking keep things pretty simple. Compile your C code with gcc and compile your Fortran code with gfortran. Linking with gfortran appears to deal with any run-time library issues. Here is an example makefile:
myprog : myprog.o load.o read.o gfortran -o myprog myprog.o load.o read.o

myprog.o : myprog.c gcc -c myprog.c load.o : load.f gfortran -c load.f read.o : read.f gfortran -c read.f

S-ar putea să vă placă și