⚠ INFORMATION
This page was translated by an AI (LLM) with a cursory human check and is awaiting full review.
This page was translated by an AI (LLM) with a cursory human check and is awaiting full review.
Calling Fortran functions from C code
Some useful recommendations:
- The 2003 Fortran standard defined a way to interface Fortran procedures with functions written in C. This solution is recommended because it ensures portability and allows the linking of any Fortran type with those of the C language. For more information, refer to Chapter 9 of the Fortran Expert course: "Interoperability between C and Fortran entities";
- Parameter passing in Fortran is done by address, while in C it is done by value;
- It is recommended to link with the Fortran compiler. If it is the
ifortcompiler, the-nofor-mainoption is necessary to indicate that themainfunction is not a Fortran function.
Be aware that if you do not adopt the solution proposed by Fortran 2003, you will be subject to the following restrictions:
- When C activates a Fortran procedure, the arguments provided during the call must be addresses of basic type objects;
- During the compilation of the Fortran program, the
-assume nounderscoreoption of theifortcompiler (-fno-underscoringif it isgfortran) must be specified so that it does not add the_character when generating the external references corresponding to the calls made in C. Obviously, if this character is indicated as a suffix during these calls, this option should not be specified; - As Fortran generates external references in lowercase, this must be respected when making calls in C.
Example of a C call
appelf.c
#include <stdio.h>
int main ()
{
int lg_chaine = 0;
float reel = 0.0;
char chaine[] = "chaîne_C";
lg_chaine = strlen(chaine);
concat( &lg_chaine, &reel, chaine);
printf("chaîne finale = %sn", chaine);
printf("longueur de la chaîne finale = %dn", lg_chaine);
printf("réel passé par adresse = %fn", reel);
return 0;
}
Example of definition in Fortran 2003/2008
concat.f90
module m
use ISO_C_BINDING, only : C_CHAR, C_INT, C_FLOAT
contains
SUBROUTINE concatenation( lg_chaine, reel, tab_car) bind(C,name='concat')
INTEGER(kind=C_INT) :: lg_chaine
REAL(kind=C_FLOAT) :: reel
CHARACTER(kind=C_CHAR), dimension(lg_chaine) :: tab_car
!
CHARACTER(kind=C_CHAR,len=lg_chaine) :: chaine
!write( chaine, '(*(a))' ) tab_car ! Format => Fortran 2008
! ou bien
do i=1,lg_chaine
chaine(i:i) = tab_car(i)
end do
!
chaine = TRIM(chaine)//' et chaîne_Fortran'
lg_chaine = LEN_TRIM(chaine)
reel = 100.0
END SUBROUTINE concatenation
end module m
# compilation
icc -c appelf.c
ifort -c concat.f90
ifort -nofor-main appelf.o concat.o -o appelf.exe
# execution
$ appelf.exe
chaîne finale = chaîne_C et chaîne_Fortran
longueur de la chaîne finale = 26
réel passé par adresse = 100.000000
Example of definition in Fortran 90/95
concat.f90
SUBROUTINE concat( lg_chaine, reel, chaine)
INTEGER, INTENT(INOUT) :: lg_chaine
REAL, INTENT(INOUT) :: reel
CHARACTER(LEN=lg_chaine), INTENT(INOUT) :: chaine
chaine = TRIM(chaine)//' et chaîne_Fortran'
lg_chaine = LEN_TRIM(chaine)
reel = 100.0
END SUBROUTINE concat
# compilation
icc -c appelf.c
ifort -c -assume nounderscore concat.f90
ifort -nofor-main appelf.o concat.o -o appelf.exe
# execution
$ appelf.exe
chaîne finale = chaîne_C et chaîne_Fortran
longueur de la chaîne finale = 26
réel passé par adresse = 100.000000