Utiliser le code Fortran en C

J’essaie d’utiliser une routine fortran en C, mais je ne travaille pas. Je ne sais pas où j’ai commis une erreur. Voici mon code Fortran, y compris Integration-Module, que je souhaite utiliser en C:

module integration implicit none contains function Integrate(func, a,b, intsteps) result(integral) interface real function func(x) real, intent(in) :: x end function func end interface real :: integral, a, b integer :: intsteps intent(in) :: a, b, intsteps optional :: intsteps real :: x, dx integer :: i,n integer, parameter :: rk = kind(x) n = 1000 if (present(intsteps)) n = intsteps dx = (ba)/n integral = 0.0_rk do i = 1,n x = a + (1.0_rk * i - 0.5_rk) * dx integral = integral + func(x) end do integral = integral * dx end function end module integration real(c_float) function wrapper_integrate(func,a,b, intsteps) result(integral) bind(C, name='integrate') use iso_c_binding use integration interface real(c_float) function func(x) bind(C) use, insortingnsic :: iso_c_binding real(c_float), intent(in) :: x end function func end interface real(c_float) :: a,b integer(c_int),intent(in) :: intsteps optional :: intsteps if (present(intsteps)) then integral = Integrate(func,a,b,intsteps) else integral = Integrate(func,a,b) endif end function wrapper_integrate 

et mon C-Code:

 #include  #include  float sin2(float x) { return sin(x) * sin(x); } float integrate(float(*func)(float), float a, float b, int intsteps); int main() { float integral; integral = integrate(sin2,0.,1.,10000); printf("%f",integral); return 0; } 

si j’exécute

 g++ -c main.c gfortran -c integration.f95 g++ main.o integration.o 

Je reçois

 undefined reference to `integrate(float (*)(float), float, float, int)' 

Est-ce que quelqu’un sait comment gérer cela?

Si vous utilisez le module ISO_C_Binding , vous pouvez directement passer une fonction de C à Fortran en tant que pointeur de fonction C_FUNPTR . Voir ici pour plus de détails.

Dans votre cas, cela ressemblerait à:

 real(c_float) function wrapper_integrate(func, a, b, intsteps) result(integral) bind(C, name='integrate') use iso_c_binding use integration abstract interface function iFunc(x) bind(C) use, insortingnsic :: iso_c_binding real(c_float) :: iFunc real(c_float), intent(in) :: x end function iFunc end interface type(C_FUNPTR), INTENT(IN), VALUE :: func real(c_float) :: a,b integer(c_int),intent(in) :: intsteps optional :: intsteps procedure(iFunc),pointer :: myfunc call c_f_procpointer(func, myfunc) if (present(intsteps)) then integral = Integrate(myfunc,a,b,intsteps) else integral = Integrate(myfunc,a,b) endif end function wrapper_integrate 

Évidemment, votre solution est plus élégante 😉

De plus, veuillez noter que Fortran transmet les variables par référence (sauf si vous spécifiez l’atsortingbut VALUE , ce que vous ne faites pas). Par conséquent, vous devez modifier votre code C en conséquence:

 #include  #include  float sin2(float *x) { return sin(*x) * sin(*x); } float integrate(float(*func)(float*), float* a, float* b, int* intsteps); int main() { float integral; float a=0.; float b=1.; int intsteps=10000; integral = integrate(sin2, &a, &b, &intsteps); printf("%f",integral); return 0; } 

Vous utilisez le compilateur C ++, pas le C Les conventions de liaison peuvent être différentes.

Et vous avez oublié de vous connecter à la bibliothèque de mathématiques (à cause du péché )

 gcc -c main.c gfortran -c integration.f95 gcc main.o integration.o -lm