⚠ 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 C functions from Fortran 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". - Parameters in Fortran are passed by address, whereas in C they are passed by value;
- Fortran character strings passed as arguments must be bounded by the
character
achar(0).
Be aware that if you do not adopt the solution proposed by Fortran 2003, you will be subject to the following restrictions:
- Only C functions whose arguments are pointers can be interfaced;
- Since C pointers are encoded on 64 bits, a Fortran procedure that wishes to retrieve such a value must do so via an integer variable of the same size;
- 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 to the C functions. Obviously, if these functions accept this character as a suffix, this option should not be indicated.
Example of C functions
fonctions.c
#include <string.h>
void fonction( char *chaine,
int *entier,
float *reel )
{
strcat( chaine, " et chaine_c" );
*entier = strlen( chaine );
*reel = 100.0;
}
typedef struct cel
{
float r;
int n;
} Cellule;
/*
* Fonction retournant l'adresse d'un objet
* de type Cellule.
*/
Cellule *creation_cel( float *r,
int *n )
{
Cellule *c = malloc( sizeof(Cellule) );
c->r = *r; c->n = *n;
return c;
}
void modif_cel( Cellule **c,
float *r,
int *n )
{
(*c)->r = *r; (*c)->n = *n;
return;
}
void imp_cel( Cellule **c )
{
printf( "Cellule : %f, %d\n", (*c)->r, (*c)->n );
return;
}
void libere_cel( Cellule **c )
{
free( *c );
return;
}
Example of a call in Fortran 2003/2008
appelc.f90
module appelC
use ISO_C_BINDING, only : C_CHAR, C_INT, C_FLOAT, C_PTR
type, bind(C) :: cel
real(kind=C_FLOAT) :: r
integer(kind=C_INT) :: n
end type cel
interface
subroutine sp(chaine, lg_chaine, reel ) bind(C,name='fonction')
import C_CHAR, C_INT, C_FLOAT
character(kind=C_CHAR),dimension(*) :: chaine
integer(kind=C_INT) :: lg_chaine
real(kind=C_FLOAT) :: reel
end subroutine sp
!
type(C_PTR) function creat( r, n ) bind(C,name='creation_cel')
import C_INT, C_FLOAT, C_PTR
real(kind=C_FLOAT) :: r
integer(kind=C_INT) :: n
end function creat
!
subroutine modif( cel, r, n ) bind(C,name='modif_cel')
import C_INT, C_FLOAT, C_PTR
type(C_PTR) :: cel
real(kind=C_FLOAT) :: r
integer(kind=C_INT) :: n
end subroutine modif
!
subroutine imp( cel ) bind(C,name='imp_cel')
import C_PTR
type(C_PTR) :: cel
end subroutine imp
!
subroutine libere( cel ) bind(C,name='libere_cel')
import C_PTR
type(C_PTR) :: cel
end subroutine libere
end interface
end module appelC
!
PROGRAM appel_c
use ISO_C_BINDING, only : C_PTR, C_F_POINTER, C_NULL_CHAR
use appelC
IMPLICIT NONE
INTEGER :: lg_chaine = 0
REAL :: reel = 0.0
CHARACTER(len=40) :: chaine = 'chaîne_Fortran'//C_NULL_CHAR
!
! Type suivant nécessaire pour la récupération d'adresse C.
type(C_PTR) :: cellule
type(cel), pointer :: p_cel
CALL sp( chaine, lg_chaine, reel )
! Suppression du caractère "C_NULL_CHAR"
chaine = chaine(1:lg_chaine)
PRINT '(2a)' ,'chaîne finale = ', chaine
PRINT '(a,i0)' ,'longueur de la chaîne finale = ', lg_chaine
PRINT '(a,f0.4)','réel passé par adresse = ', reel
cellule = creat( acos(-1.), 1756 )
call C_F_POINTER( CPTR=cellule, FPTR=p_cel )
call imp( cellule )
call modif( cellule, exp(1.), 1791 )
call imp( cellule )
call libere( cellule )
END PROGRAM appel_c
#compilation
icc -c fonctions.c
ifort appelc.f90 fonctions.o -o appelc.exe
#execution
$ ./appelc.exe
chaîne finale = chaîne_Fortran et chaine_c
longueur de la chaîne finale = 26
réel passé par adresse = 100.0000
Cellule : 3.141593, 1756
Cellule : 2.718282, 1791
Example of a call in Fortran 90/95
appelc.f90
PROGRAM appel_c
IMPLICIT NONE
INTEGER :: lg_chaine = 0
REAL :: reel = 0.0
CHARACTER(len=40) :: chaine = 'chaîne_Fortran'//achar(0)
!
! Type suivant nécessaire pour la récupération d'adresse C.
INTEGER(kind=8) :: creation_cel, cellule
CALL fonction( chaine, lg_chaine, reel )
! Suppression du caractère "achar(0)"
chaine = chaine(1:lg_chaine)
PRINT '(2a)' ,'chaîne finale = ', chaine
PRINT '(a,i0)' ,'longueur de la chaîne finale = ', lg_chaine
PRINT '(a,f0.4)','réel passé par adresse = ', reel
cellule = creation_cel( acos(-1.), 1756 )
call imp_cel( cellule )
call modif_cel ( cellule, exp(1.), 1791 )
call imp_cel( cellule )
call libere_cel( cellule )
END PROGRAM appel_c
#compilation
icc -c fonctions.c
ifort -assume nounderscore appelc.f90 fonctions.o -o appelc.exe
#execution
$ ./appelc.exe
chaîne finale = chaîne_Fortran et chaine_c
longueur de la chaîne finale = 26
réel passé par adresse = 100.0000
Cellule : 3.141593, 1756
Cellule : 2.718282, 1791