Vargas : appel des fonctions C à partir de Fortran
Quelques recommandations utiles :
- Le passage des paramètres en Fortran s'effectue par adresse, alors
qu'en C la transmission se fait par valeur.
Les arguments de la fonction C doivent être des pointeurs dont la taille
dépendent de l'option d'adressage -q32/64 utilisée
lors de la compilation Fortran.
- Les chaînes de caractères Fortran passées en arguments doivent être
terminées par le caractère char(0).
- En adressage 64 bits (par défaut à l'IDRIS)
les pointeurs C étant codés sur 64 bits, une procédure Fortran
qui désire récupérer une telle valeur devra le faire via
une variable entière sur 64 bits.
Vargas : cat appelc.f90
PROGRAM appel_c
IMPLICIT NONE
INTEGER :: lg_chaine = 0
REAL :: reel = 0.0
CHARACTER(len=40) :: chaine = 'chaine_Fortran' // char(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 )
PRINT*,'chaîne finale = ', chaine
PRINT*,'longueur de la chaîne finale = ', lg_chaine
PRINT*,'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
Vargas : cat fonction.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 une adresse "long int" (64 bits).
*/
long creation_cel( float *r,
int *n )
{
Cellule *c = malloc( sizeof( Cellule ) );
c->r = *r; c->n = *n;
/*
* Attention : lors de la conversion "pointeur=>entier"
* --------- suivante, utilisez un "cast" avec le type
* "long" (sur 64 bits) afin de préserver la
* valeur du pointeur.
*/
return (long)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 );
}
void libere_cel( Cellule **c )
{
free( *c );
}
Vargas : cc -c fonction.c
Vargas : f90 appelc.f90 fonction.o
Vargas : ./a.out
chaine finale = chaine_Fortran et chaine_c
longueur de la chaine finale = 26
reel passe par adresse = 100.0000000
Cellule : 3.141593, 1756
Cellule : 2.718282, 1791
Remarques :
- si les noms des fonctions C sont suffixés par le caractère '_',
il sera nécessaire de spécifier l'option -qextname lors
de la compilation du code Fortran,
- avant d'appeler des fonctions C il faut savoir qu'il
existe des fonctions Fortran pour connaître l'environnement d'exécution
(getarg, iargc, getenv, ...)
et que Fortran 90 a apporté de nouvelles fonctions intrinsèques (sur le
traitement des chaînes de caractères par exemple).
© CNRS - IDRIS, 13/01/2012