Vargas : appel des fonctions C à partir de Fortran


Quelques recommandations utiles :
  1. 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.
  2. Les chaînes de caractères Fortran passées en arguments doivent être terminées par le caractère char(0).
  3. 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 :


© CNRS - IDRIS, 13/01/2012