将接口模块过程从fortran导入C

Posted

技术标签:

【中文标题】将接口模块过程从fortran导入C【英文标题】:importing interface module procedure from fortran into C 【发布时间】:2017-06-14 00:42:07 【问题描述】:

我应该如何使用 extern 将 fortran interface 导入到 C 中?

假设我有以下 fortran 模块:

!swapper module
module swapper
   interface swap
      module procedure swap_r, swap_i, swap_c
   end interface
contains
    !subroutine implementations here:
    !swap_r takes two double precision as argument
    !swap_i takes two integers as argument
    !swap_c takes two characters as argument
end module swapper

那我可以只用C做以下吗?

extern "C" void __swapper_MOD_swap(double*, double*)
extern "C" void __swapper_MOD_swap(int*, int*)
extern "C" void __swapper_MOD_swap(char*, char*)

或者,如果我承诺只用双精度数字调用swap,我可以专门这样做吗?

extern "C" void __swapper_MOD_swap(double*, double*)

【问题讨论】:

也许这对你有帮助,docs.cray.com/books/S-2179-52/html-S-2179-52/ppgzmrwh.html。 C 中没有泛型。但 C++ 中有泛型。而且C中没有extern "C"。你真的在用C++吗? 这里有更多关于“INTERFACE”的信息:people.sc.fsu.edu/~jburkardt/f_src/f90_calls_c++/… 【参考方案1】:

看起来您实际上是在使用 C++。但首先让我们回答 C 或 C 风格的 C++:

不,你不能这样做

extern "C" void __swapper_MOD_swap(double*, double*)

你不能对三种不同类型的参数这样做,你甚至不能对单一类型的参数这样做。

首先,库中实际上不应该有任何__swapper_MOD_swap

Fortran 的作用是为三个特定的子例程swap_r, swap_i, swap_c 保留一个接口(这只是描述如何调用某些东西),并允许您通过名称swap 调用它。

但是模块中没有实际的子例程swap!!! Fortran 只会让您以不同的名称调用这三个细节,仅此而已。

没有办法像泛型那样从 C 中调用这些函数。 C 没有这种类型的泛型!(它确实有一些函数可以使用void* 对任何类型进行操作)。


在 C++ 中,您实际上可以创建专门用于不同类型的泛型,您可以将 Fortran 过程称为泛型,但您必须自己告诉 C++!您可以制作模板并手动专门化此模板以调用适当的extern "C" 函数。

例如,请参阅我的标题 https://github.com/LadaF/PoisFFT/blob/master/src/poisfft.h,其中我创建了一个链接到 extern "C" struct 的 C++ 类和一些 extern "C" 函数,但这些函数都在 Fortran 中实现。


最后,不要使用__swapper_MOD_ 符号。使用 bind(C,name="some_name") 创建一些 Fortran 绑定并通过 extern "C" 调用 some_name,因为不同的 Fortran 编译器使用不同的名称修饰方案。

【讨论】:

感谢您的详细回复,包括有关最佳做法的提示!

以上是关于将接口模块过程从fortran导入C的主要内容,如果未能解决你的问题,请参考以下文章

Fortran 中的 INTERFACE 块和 MODULE 过程之间的区别是啥?

在Fortran中,在扩展定义中,如何将公共过程设置为私有?

如何创建接口以将 c 字符数组转换为 fortran

如何在Fortran中复制未知类型的数据?

在Fortran中正确使用模块,子例程和函数

使用优化模块的 Scipy 错误。将数组转换为 fortran 失败