将 fortran 77 函数传递给 C/C++
是否可以将 fortran 77 函数作为回调函数指针传递给 C/C++?如果有,怎么做?
Is it possible to pass fortran 77 function as a callback function pointer to C/C++? if so, how?
我在网上找到的信息与 fortran 90 及更高版本有关,但我的旧代码库在 77 中.
information I found on the web relates to fortran 90 and above, but my legacy code base is in 77.
非常感谢
推荐答案
如果可以在 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 添加这个新功能?
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?
我已经使用 ISO C 绑定从 C 调用 Fortran 过程,但没有将它们作为指针传递.这应该是可能的.步骤是:
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) 使用 Bind(C) 属性声明 Fortran 函数,
1) you declare the Fortran function with the Bind(C) attribute,
2) 您使用特殊类型声明所有参数,例如 integer(c_int),与 C 的类型匹配.
2) you declare all of the arguments using special types, such as integer(c_int), that match the types of C.
步骤 1 和2 使 Fortran 函数可与 C 互操作.
Steps 1 & 2 make the Fortran function interoperable with C.
3) 使用 Fortran 内部函数c_funloc"获得指向此 Fortran 函数的 C 指针,将指针值分配给类型为c_funptr"的指针.
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) 在 Fortran 代码中,使用接口声明要将函数指针传递给的 C 例程,用 Fortran 术语声明它,但使用 Bind(C) 属性和可互操作的类型,以便 Fortran编译器知道使用 C 调用约定――使 C 例程可与 Fortran 互操作.
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.
然后当您在 Fortran 代码中调用 C 例程时,您可以将步骤 3 中创建的函数指针传递给它.
Then when you call the C-routine in the Fortran code, you can pass it the function pointer created in step 3.
更新:代码示例:Fortran 主程序test_func_pointer"将指向 Fortran 函数my_poly"的指针传递给 C 例程C_Func_using_Func_ptr"并从该 C 函数接收结果.
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
和
float C_Func_using_Func_ptr (
float x,
float (*Func_ptr) (float y)
) {
return ( (*Func_ptr) (x) );
}
相关文章