从 Fortran 访问 C++ 结构数组?
Posted
技术标签:
【中文标题】从 Fortran 访问 C++ 结构数组?【英文标题】:Access array of C++ structs from Fortran? 【发布时间】:2013-08-09 20:21:12 【问题描述】:在 C++ 中,我分配了一个 S 数组。在 Fortran 中,我想访问这个数组的元素。我该怎么做?
C++:
struct S double a; double b;;
S *arrayOfS;
arrayOfS = (S *)new S[123]; // allocate
Fortran 2003:
USE ISO_C_Binding
TYPE, BIND(C) :: SFortran
REAL(c_double) :: a,b
END TYPE SFortran
S 和 SFortran 现在应该可以互操作了,但我还需要有一种方法来访问在 C++ 中声明的数组的元素。我想让 Fortran 中的 SC(5)%a 对应于 C++ 中的 arrayOfS[4].a 。如何为将具有此访问权限的 Fortran 数组 SC 声明和设置正确的值?
【问题讨论】:
您不需要在 C++ 中强制转换new
的返回值。虽然我在吹毛求疵,但将初始化程序与声明放在一起是惯用的:S* arrayOfS = new S[123];
而不是单独的行。
演员表是为了清楚起见。同一行与单独行是“圣战”问题。但这也不是生产代码;这是一个让问题更清楚的简化示例。
【参考方案1】:
你可以:
1) 将 C++ 数组传递给采用适当数组参数的 Fortran BIND(C) 过程。
SUBROUTINE proc(array) BIND(C, NAME='proc')
...
TYPE(SFortran) :: array(*)
使用这种方法,您可能还希望传递数组的大小并使数组参数具有显式形状。
b) 将数组指针作为 C++ 端的 extern "C" 全局变量,然后通过 Fortran 模块变量与 BIND(C) 进行互操作。
MODULE some_module
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_F_POINTER
...
TYPE(C_PTR), BIND(C, NAME='arrayOfS') :: array_ptr
...
! In a procedure in the module...
TYPE(SFortran), POINTER :: array(:)
CALL C_F_POINTER(array_ptr, array, [123])
同样,它可能适合单独提供数组的大小以避免在 C_F_POINTER 参考中对其进行硬编码。
哪种方法最好取决于您的要求!
【讨论】:
使用 Intel Fortran 编译器 XE 12.1.3.300,我得到一个链接错误“未定义的外部符号 c_f_pointer_set_scalar”。导致此错误的源代码行是“CALL C_F_POINTER(scPtr, sc, 1)”,其中 scPtr 对应于您的 array_ptr,sc 对应于您的“数组”。无论是在英特尔的文档中还是通过 Google,我都找不到对 c_f_pointer_set_scalar 的任何引用。有什么建议吗? 这表明您没有在链接步骤中包含英特尔 Fortran 运行时库之一。在 Windows 上,该过程在 ifmodintr.lib 中定义。 正确! Link 使用的是 IVF 11.1.065 中的库。我把它改成了 Composer XE 2011 SP1\Compiler\lib\ia32,链接错误消失了。以上是关于从 Fortran 访问 C++ 结构数组?的主要内容,如果未能解决你的问题,请参考以下文章
用于从 FORTRAN 代码调用的 C++ 函数调用 C++ 代码的 Cmake 配置文件