Fortran接口调用返回指针的C函数

我有一个C函数,

double* foofunc() { /* Function Body */ } 

我不知道如何在Fortran声明一个接口来调用这个C函数。

此外,如果指针应该指向GPU device memory ,我怎么能在Fortran界面中定义它? 我是否需要使用DEVICE属性。

请使用Fortran支持的function,直到2003年。

有什么建议?

由于您使用的是Fortran 2003,因此使用ISO C绑定可以轻松地连接Fortran和C. (大多数Fortran 95编译器现在都支持ISO C绑定,即使它们不是完整的Fortran 2003编译器。)这远远好于早期答案中提出的复杂方法,这在早期的时代是必要的 – 它是语言的一部分,因此是可移植的,与编译器和平台无关。 但Fortran 2003版本并没有涵盖任何可能性。 (下一个Fortran将添加与C接口的其他情况。)您可以轻松传递一个C指针的参数 – 只需在Fortran声明中省略“value”atttribute。 指向指针的指针需要C_PTR。 我不知道指针作为一个函数返回…我必须在有时间时进行实验。 如果必须,请创建一个简单的C glue例程,将函数返回的指针转换为参数 – 这种情况很简单。

重新指向GPU设备内存 – 除非您的编译器具有非标准function,否则它将不具有“DEVICE”。 也许“波动”会有所帮助吗? 创建适当的用户定义类型……

gfortran手册中有“与C的互操作性”中的示例。 由于这是该语言的一部分,即使您不使用gfortran,此文档也应该有所帮助。

正如MSB所说,使用fortran 2003 C互操作性function是最简单的。
只需将函数结果声明为type(c_ptr) ,并通过调用c_f_pointer将其转换为fortran指针。

以下简单示例在编译时使用:
gfortran foo.f03 foofunc.c -o foo.exe
(gfortran版本4.5.0)

foo.f03的内容:

 program foo use, intrinsic :: iso_c_binding, only : c_ptr, & c_f_pointer, & c_double implicit none type(c_ptr) :: c_p real(c_double), pointer :: f_p interface function foofunc() bind(c) import :: c_ptr implicit none type(c_ptr) :: foofunc end function foofunc end interface c_p = foofunc() call c_f_pointer(c_p, f_p) print *, f_p end program foo 

foofunc.c的内容:

 double bar = 2; double *foofunc() { return &bar; } 

不过,我不知道它对指向GPU设备内存的效果如何。 从来没有处理过。

您想从Fortran程序中调用C函数。 有很多方法。

一种方法是将C例程转换为fortran。 如果您的C程序冗长,复杂且经过充分测试,那么对您来说可能并不是一件容易的选择。 另一种方法是将fortran转换为C.可能存在类似的问题。

如果您无法解决上述问题,那么您必须面对如下问题。

在编程用语中,它被称为混合语言编程。

我不知道哪种语言和操作系统U正在使用。 因此,我将在下面给出四种替代方法,而不是提供现成的解决方案。 我已经使用了所有已实现的应用程序 前两个是那些幸运拥有强大操作系统(现在是一种稀有商品)的人。 该程序运行速度快,适合硬实时工作。 最后两个适用于任何操作系统,但程序运行缓慢,特别是在频繁调用C例程的情况下。 您还需要在所有方法中进行更多的编程工作。 还要注意,您的C函数会在每个备选项中返回一个指针。

  1. 一些fortran编译器(不是全部)允许调用非fortran函数。 这需要操作系统中运行fortran和C的适当设施。 在这种情况下,在过程调用期间使用相同的堆栈管理。 请仔细阅读两种语言和代码的程序员手册。

  2. 如果这是不可能的,那么你可以欺骗操作系统这样做,但你需要一个用汇编程序编写的中间函数。 您从fortran调用汇编程序例程,然后从汇编程序调用C例程并以相反的方式返回。 您需要了解Fortran,Assembler和C三者的堆栈管理细节,并编写用于将fortran堆栈转换为C堆栈的代码。 这将在汇编程序中。

在上述两种方法中,您必须了解您的链接器(或活页夹)的工作方式,您可能需要在那里做一些额外的工作。 在任何一种情况下,它都是相同的.exe文件,因此您的程序将快速运行。 在这样的操作系统中,任何语言,彼此都很奇怪,可以混合使用。 甚至可以使用DLL。 如果运行时库使用与C函数具有相同名称但执行不同作业的fortran函数,则只会出现复杂性。 支持混合语言编程的操作系统通常会为您提供一些防止这种情况的工

  1. 如果上述替代方案不可行,则将fortran和C程序作为单独的.exe运行,并将它们作为两个并发进程运行。 (注意它们甚至可以在不同操作系统下的同一台计算机或不同的计算机上!)。 现在,无论何时需要从fortran调用C,都可以通过任何可用的进程间通信机制传递所有参数和数据,比如管道,套接字或其他任何内容。 C程序可以通过类似的机制返回数据。 一定要添加适当的代码来处理通过进程间通信传递的参数。 同步两个进程并区分旧数据和最近的数据也是你的工作。 不需要堆栈管理。

  2. 这个适用于那些不喜欢堆栈,同步,链接器或任何需要智能的东西的人。 如果必须经常调用C程序,程序将运行得最慢。 反直觉地,如果C程序只需要调用一次,那么这也是最智能的解决方案! 将数据从fortran程序输出到磁盘(平面文件或数据库)。 然后调用C程序从同一文件读取并以相同的方式将数据返回到fortran。 在更改语言之前要小心关闭文件。 处理文件输入 – 输出调用中的所有错误。 否则你崩溃了。

你的答案与我的答案中的第1点相同(1.一些fortran编译器……)。 然而,您提到“但Fortran 2003版本并未涵盖所有可能性”。 这是一个实际的观点

程序员经常达到目标; 即使最新版本的编译器或连接器不可用,也可能出现问题。 我已经给出了现场测试的替代品 学生有一种选择,另一种是“实时”问题。 这可能需要更长的时间,但在您获得与另一种语言完美接口的Fortran版本之前该怎么做。

如果您现有的调试fortran和C程序一起长达30,000行,那么在2000客户端系统中使用新版本的编译器可能会解除许多其他问题。 人们在这些问题上花费的时间比使用现有编译器和操作系统中的常用资源自己编写一些连接器要多花一些时间。 我们在对应用程序的所有组件进行全新测试后实现新的编译器。 黄金法则是“使用已知error handling现有编译器比使用其最新版本具有未知错误更容易”。 该规则仅适用于大的实际问题。