从 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++ 结构数组?的主要内容,如果未能解决你的问题,请参考以下文章

将 char 数组从 c++ 传递到 fortran

将 C++ 字符数组传递给 Fortran

将 C++ 字符数组传递给 Fortran

用于从 FORTRAN 代码调用的 C++ 函数调用 C++ 代码的 Cmake 配置文件

将 mpi 消息从 c++ 代码发送到 fortran 90 代码

在 C++ 和 Fortran 代码之间传递复数数组