передать функцию fortran 77 в C / C ++ - PullRequest
4 голосов
/ 25 мая 2010

Можно ли передать функцию fortran 77 как указатель на функцию обратного вызова в C / C ++? если да, то как?

информация, которую я нашел в сети, относится к фортрану 90 и выше, но моя устаревшая кодовая база - 77.

большое спасибо

1 Ответ

6 голосов
/ 25 мая 2010

Если это можно сделать в FORTRAN 77, это будет зависеть от компилятора и платформы. Новое связывание ISO C в Fortran 2003 предоставляет стандартный способ смешивания Fortran и C и любого языка, который следует или может следовать соглашениям о вызовах C, таких как C ++. Хотя формально является частью Fortran 2003, и хотя существует очень мало компиляторов Fortran, которые полностью поддерживают весь Fortran 2003, привязка ISO C поддерживается многими компиляторами Fortran 95, включая gfortran, g95, Sun, ifort и т. Д. Итак, я рекомендуем использовать один из этих компиляторов Fortran 95 и метод привязки ISO C, а не выяснять какой-либо метод для конкретного метода. Поскольку FORTRAN 77 является подмножеством Fortran 95, почему бы не скомпилировать свой прежний код с одним из этих компиляторов, используя Fortran 95 для добавления этой новой функции?

Я вызывал процедуры Фортрана из C, используя привязку ISO C, но не передавал их как указатели. Это должно быть возможно. Шаги:

1) вы объявляете функцию Фортрана с атрибутом Bind (C),

2) вы объявляете все аргументы, используя специальные типы, такие как целое число (c_int), которые соответствуют типам C.

Шаги 1 и 2 делают функцию Фортрана совместимой с C.

3) Вы получаете C-указатель на эту функцию Fortran с помощью встроенной функции Fortran "c_funloc", присваивающей значение указателя указателю типа "c_funptr".

4) В коде Fortran вы объявляете подпрограмму C, на которую вы хотите передать указатель функции через интерфейс, объявляя ее в терминах Fortran, но используя атрибут Bind (C) и совместимые типы, так что Fortran Компилятор знает, как использовать соглашение о C-вызовах - что делает процедуру C совместимой с Fortran.

Затем, когда вы вызываете подпрограмму C в коде Фортрана, вы можете передать ей указатель функции, созданный на шаге 3.

ОБНОВЛЕНИЕ: Пример кода: основная программа Fortran "test_func_pointer" передает указатель на функцию Fortran "my_poly" в подпрограмму C "C_Func_using_Func_ptr" и получает результат обратно из этой функции C.

module func_pointer_mod

   use, intrinsic :: iso_c_binding

   implicit none

   interface C_func_interface

      function C_Func_using_Func_ptr ( x, Func_ptr ) bind (C, name="C_Func_using_Func_ptr")

         import

         real (c_float) :: C_Func_using_Func_ptr
         real (c_float), VALUE, intent (in) :: x
         type (c_funptr), VALUE, intent (in) :: Func_ptr

      end function C_Func_using_Func_ptr

   end interface C_func_interface


contains

   function my_poly (x) bind (C, name="my_poly")

      real (c_float) :: my_poly
      real (c_float), VALUE, intent (in) :: x

      my_poly = 2.0 * x**2 + 3.0 * x + 5.0

      return

   end function my_poly

end module func_pointer_mod


program test_func_pointer

   use, intrinsic :: iso_c_binding

   use func_pointer_mod

   implicit none

   type (c_funptr) :: C_func_ptr

   C_func_ptr = c_funloc ( my_poly )

   write (*, *) C_Func_using_Func_ptr ( 2.5_c_float, C_func_ptr )

   stop

end program test_func_pointer

и

float C_Func_using_Func_ptr (

   float x,
   float (*Func_ptr) (float y)

) {

   return ( (*Func_ptr) (x) );

}
...