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, %d\n", (*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 :

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 

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++

© CNRS - IDRIS, 23/04/2012