将 fortran 77 函数传递给 C/C++

发布于 2024-09-02 19:26:55 字数 120 浏览 8 评论 0原文

是否可以将 fortran 77 函数作为回调函数指针传递给 C/C++? 如果是这样,怎么办?

我在网上找到的信息与 Fortran 90 及以上版本相关,但我的遗留代码库是 77。

非常感谢

Is it possible to pass fortran 77 function as a callback function pointer to C/C++?
if so, how?

information I found on the web relates to fortran 90 and above, but my legacy code base is in 77.

many thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

娇妻 2024-09-09 19:26:55

如果它可以在 FORTRAN 77 中完成,那么它将是特定于编译器和平台的。 Fortran 2003 的新 ISO C 绑定提供了混合 Fortran 和 C 以及任何遵循或可以遵循 C 调用约定的语言(例如 C++)的标准方法。虽然正式成为 Fortran 2003 的一部分,并且完全支持整个 Fortran 2003 的 Fortran 编译器极少,但 ISO C 绑定受到许多 Fortran 95 编译器的支持,包括 gfortran、g95、Sun、ifort 等。建议使用这些 Fortran 95 编译器之一和 ISO C 绑定方法,而不是为特定方法找出某种方法。由于 FORTRAN 77 是 Fortran 95 的子集,为什么不使用这些编译器之一来编译旧代码,使用 Fortran 95 添加此新功能呢?

我已经使用 ISO C 绑定从 C 调用了 Fortran 过程,但没有将它们作为指针传递。这应该是可能的。步骤是:

1) 使用 Bind(C) 属性声明 Fortran 函数,

2) 使用与 C 类型匹配的特殊类型(例如整数(c_int))声明所有参数

。 2 使 Fortran 函数与 C 互操作。

3) 使用 Fortran 内部函数“c_funloc”获得指向该 Fortran 函数的 C 指针,并将该指针值赋给“c_funptr”类型的指针。

4) 在 Fortran 代码中,您可以使用 Interface 来声明要向其传递函数指针的 C 例程,以 Fortran 术语进行声明,但使用 Bind(C) 属性和可互操作类型,以便 Fortran 编译器知道使用 C 调用约定——使 C 例程可与 Fortran 互操作。

然后,当您在 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) );

}

If it can be done in FORTRAN 77, it will be compiler and platform specific. The new ISO C Binding of Fortran 2003 provides a standard way of mixing Fortran and C, and any language that follows or can follow the calling conventions of C, such as C++. While formally a part of Fortran 2003, and while there are extremely few Fortran compilers that fully support the entirety of Fortran 2003, the ISO C Binding is supported by numerous Fortran 95 compilers, including gfortran, g95, Sun, ifort, etc. So I recommend using one of these Fortran 95 compilers and the ISO C Binding method rather than figuring out some method for a particular method. Since FORTRAN 77 is a subset of of Fortran 95, why not compile your legacy code with one of these compilers, using Fortran 95 to add this new feature?

I have called Fortran procedures from C using the ISO C Binding, but haven't passed them as pointers. It should be possible. The steps are:

1) you declare the Fortran function with the Bind(C) attribute,

2) you declare all of the arguments using special types, such as integer(c_int), that match the types of C.

Steps 1 & 2 make the Fortran function interoperable with C.

3) You obtain a C-pointer to this Fortran function with the Fortran instrinsic function "c_funloc", assigning the pointer value to a pointer of type "c_funptr".

4) In the Fortran code, you declare the C routine that you want to pass the function pointer to with an Interface, declaring it in in Fortran terms, but using the Bind(C) attribute and interoperable types so that the Fortran compiler knows to use the C-calling convention -- making the C routine interoperable with Fortran.

Then when you call the C-routine in the Fortran code, you can pass it the function pointer created in step 3.

UPDATE: Code example: The Fortran main program "test_func_pointer" passes a pointer to the Fortran function "my_poly" to the C routine "C_Func_using_Func_ptr" and receives the result back from that C function.

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

and

float C_Func_using_Func_ptr (

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

) {

   return ( (*Func_ptr) (x) );

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文