Babel : appel des fonctions C/C++ à partir de Fortran

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

L'interfacage peut également se faire en utilisant les fonctionnalités d'interfacage du langage Fortran 2003.

Exemple

Babel : **cat appelc.f90**
PROGRAM appel_c
  IMPLICIT NONE

  INTEGER           ::  lg_chaine = 0
  REAL              ::  reel      = 0.0
  CHARACTER(len=40) ::  chaine    = 'chaine_Fortran'  char(0)
!
  INTEGER           ::  creation_cel, cellule

  CALL fonction( chaine, lg_chaine, reel )

  chaine =  suppression_null_char( chaine )
  PRINT*,'chaîne finale                  = ', trim(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 )
contains
  function suppression_null_char( ch )
    character(len=*), intent(in) :: ch
    character(len=len(ch))       :: suppression_null_char
    integer i

    i = index( ch, char(0) )
    suppression_null_char = ch
    suppression_null_char(i:i) = ' '
  end function suppression_null_char
END PROGRAM appel_c

Babel : **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;

  return;
}

typedef struct cel
{
  float r;
  int   n;
} Cellule;

int creation_cel( float *r,
                  int   *n )
{
  Cellule *c = malloc( sizeof( Cellule ) );

  c->r = *r; c->n = *n;

  return (int)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, %dn'', (*c)->r, (*c)->n );

  return;
}

void libere_cel( Cellule **c )
{
  free( *c );

  return;
}

Babel : **mpixlc -c fonction.c**
Babel : **mpixlf90_r appelc.f90 fonction.o**
Babel : **bgrun -np 1 -exe ./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).

Appel de fonctions C++ à partir de Fortran

La plupart des remarques pour le C s'appliquent également au C++.

Toutes les procédures devant être accessibles à partir du Fortran doivent être déclarées extern C.

Lors de l'édition de liens, il faut s'assurer que les bibliothèques C++ sont bien trouvées. Pour cela, il suffit d'ajouter -L/opt/ibmcmp/vacpp/bg/9.0/lib -libmc++ -lstdc++.

Exemple

Babel : **cat main.f90**
program toto
 call printcxx
end program

Babel : **cat printcxx.cxx**
#include <iostream>

extern ''C''
{
extern void printcxx();
}

void printcxx()
{
  std::cout << ''printcxx ok'' << std::endl;
}

Babel : mpixlcxx_r -c printcxx.cxx
Babel : mpixlf90 main.f90 printcxx.o -L/opt/ibmcmp/vacpp/bg/9.0/lib -libmc++ -lstdc++