2010-05-13 4 views
2

J'essaye d'appeler une fonction C++ dans un sous-programme Fortran. Cette fonction C++ est supposée mettre à jour un tableau d'entiers. Voici un code non-travail que j'ai écrit. Quelle est la solution?Passer un tableau int Fortran à C++ en appelant la fonction C++ dans Fortran

! Fortran function that calls a C++ function. 

subroutine my_function() 

     integer(4) ar(*) 

     integer(4) get_filled_ar 

     ! Need correct syntax here. 
     ar = get_filled_ar() 
end 


// C++ function: 

    extern "C" { 
     void get_filled_ar(int *ar){ 
      ar[0] = 1; 
      ar[1] = 10; 
      ar[3] = 100; 
     } 
    } 

Répondre

2

Voici un programme complet avec votre code dans ce qui devrait fonctionner (au moins sur linux avec gcc/gfortran).

Dans le fichier Fortran fortran.f, mis:

 IMPLICIT NONE  
    CALL my_function() 
    END 

! FORTRAN function that calls a C++ function 

    subroutine my_function() 
! Tell fortran about the C++ function: 
     external get_filled_ar 

     integer ar(4) 

! As the C++ function returns void, call it as a subroutine in 
! fortran: 
     call get_filled_ar(ar) 
! To check it worked, print out the numbers: 
     do i = 1,4 
      write(*,*) i,"->",ar(i) 
     enddo 
    end 

En cplusplus.cc put:

extern "C" 
{ 
    void get_filled_ar_(int* ar) // note extra underscore to keep linker happy 
    { 
    ar[0] = 1; 
    ar[1] = 10; 
    ar[3] = 100; 
    }  
} 

ensuite construire (sur linux avec gcc/gfortran, pourraient être différents sur d'autres systèmes) avec:

gfortran -c fortran.f 
gcc -c cplusplus.cc 
gfortran -o program-name fortran.o cplusplus.o 
+0

Merci pour le code détaillé. Dans votre extrait de code, vous avez affecté une taille fixe au tableau ar. Je veux que ar soit un tableau dynamique. Je vais vérifier si cela fonctionne aussi pour un tableau dynamique – cppb

5

Avec Fortran 200 3 il existe un moyen standard et donc indépendant de la plate-forme et du compilateur pour appeler C à partir de Fortran, ainsi que tout langage qui utilise l'interface d'appel C. Aussi pour appeler Fortran à partir de C. Alors que les différents compilateurs ajoutent progressivement des fonctionnalités Fortran 2003 et qu'il existe peu de compilateurs 2003 complets, la liaison ISO C est disponible depuis un certain temps dans de nombreux compilateurs. La liaison ISO C fonctionne mieux que les techniques ad hoc précédentes, qui étaient parfois mal documentées, et variées entre les compilateurs et les plates-formes. Pour appeler C depuis Fortran, vous écrivez une "interface" qui indique au compilateur Fortran qu'il doit utiliser les conventions d'appel C et les types C.

Voici un exemple. Comme l'a écrit Mike, puisque la fonction C++ renvoie void, traitez-la dans le Fortran comme un sous-programme et appelez-la. Ainsi, il n'a pas besoin d'être donné un type. En outre, quelque part dans le Fortran, vous devez réserver le stockage pour le tableau - le plus simple est une déclaration avec une valeur numérique pour la dimension. Et vous avez besoin d'un programme principal dans une langue.

program test_call_C 

use iso_c_binding 

implicit none 

interface c_interface 

    subroutine get_filled_ar (ar) bind (C, name = "get_filled_ar") 

    use iso_c_binding 

    implicit none 

    integer (c_int), intent (out), dimension (*) :: ar 

    end subroutine get_filled_ar 

end interface c_interface 


integer (c_int), dimension (0:3) :: ar 

call get_filled_ar (ar) 

write (*, *) "Fortran: ar:", ar 

stop 

end program test_call_C 

et C:

void get_filled_ar (
    int ar [] 
) { 

    ar [0] = 1; 
    ar [1] = 10; 
    ar [2] = 100; 

    return; 

} 

Exemples de commandes:

gcc -c get_filled_ar.c 
gfortran get_filled_ar.o test_call_C.f90 -o test_call_C.exe 
./test_call_C.exe 

Pour appeler votre code C++, utilisez les commandes suivantes. Le nom spécifié dans le "bind" évite le besoin d'un soulignement de fin pour que votre code C++ fonctionne directement.

g++ -c cplusplus.cc 
gfortran cplusplus.o test_call_C.f90 -o test_call_Cplusplus.exe 
./test_call_Cplusplus.exe 
+0

+1 - c'est certainement une meilleure solution que la mienne si votre compilateur le supporte. –

+0

@MSB: Merci pour une réponse détaillée. – cppb

+0

'ar' est défini comme' integer (c_int), dimension (0: 3) :: ar' dans le code fortran. Que pouvez-vous faire si vous n'avez aucun contrôle sur cette définition? c'est-à-dire que vous obtenez un paramètre 'integer * 8, intention (inout) :: ar (num)'? –