【问题标题】:What is the equivalent type in C for REAL(KIND=real_normal) in Fortran?Fortran 中 REAL(KIND=real_normal) 在 C 中的等效类型是什么?
【发布时间】:2010-07-20 03:18:08
【问题描述】:

我在将数组从 Fortran 传递到 c 函数时遇到问题: 在 fortran 中,数组定义为

REAL(KIND=real_normal) , DIMENSION(:), ALLOCATABLE :: array
call cFunc(array)

如果将 cFunc 定义为

void cFunc(double *data){...}

比数据只包含“垃圾”值。这种情况下问题出在哪里? (使用整数可以很好地解决这个问题)。

谢谢。 编辑: 我的平台: 编译器:VS 2008,Intel编译器11版本 操作系统:Win7

编辑 2: 我这样定义c函数的接口(代码简化为一个元素,这会产生问题,真正的函数有更多的参数):

interface c_interface

subroutine cFunc(array) bind (C, name = "cFunc")
use iso_c_binding
REAL(c_double), DIMENSION(*)::array
end subroutine cFunc

fortran 中的内存是用

分配的
ALLOCATE (array(numberOfElements))
call cFunc(array)

目前我收到运行时错误“浮点溢出”。在某些情况下,数组正确的元素。

【问题讨论】:

  • 您只是向我们展示了 cFunc 的声明——数据的接收者。我们需要看调用代码(数据的发送者)
  • 你在什么平台上编译这个?您应该列出操作系统和芯片架构,因为这可能会有所不同。
  • real_normal 的确切定义是什么?并在调用 cFunc 之前分配了数组?在 fortran 中阅读有关 C 绑定的内容并使用诸如 c_double 之类的内容可能会有所帮助。如果您搜索iso +c binding fortran,您会找到一些阅读内容;或者在你的 fortran 编译器的手册中,如果它提供了模块。
  • 我认为,使用 c_double 的方式有效。如果你回答我的问题,我会接受。
  • 我做C/Fortran接口已经快20年了,但我还记得一点。 REAL 通常是 32 位浮点数。但是我认为 Fortran 过去常常为数组的长度(32 位 int)添加一个额外的参数。此外,在 Windows 上,Fortran 过去使用 __WINAPI 参数传递而不是基本的 C 传递。

标签: c++ c fortran


【解决方案1】:

片段REAL(KIND=real_normal) 不是数据类型的完整和标准规范。在您拥有的源代码中必须有变量real_normal 的声明。我猜它是这样声明的,array 是 4 字节或 8 字节浮点数,但这只是一个猜测。 array 不是默认浮点数数组(Fortran 称为 real)。

正如其他回答者所建议的那样,研究 Fortran 2003 的 与 C 功能的互操作性。如果您的编译器没有实现这些功能,请放弃它并获得一个可以实现的编译器。

【讨论】:

    【解决方案2】:

    @High Performance Mark 的建议非常好,我强烈推荐 Fortran 2003 的 ISO_C_Binding(由众多 Fortran 编译器支持)以实现 Fortran 和 C 之间的互操作性——这里有一个更大的问题使 ISO_C_Binding 更有用:Fortran可分配数组比普通数组更复杂。如果你“破解”它并直接传递一个指向 C 代码的指针,你很可能传递一个指向描述可分配数组的 Fortran 内部结构的指针,而不是指向数值序列的指针。 ISO_C_Binding 不直接支持可分配数组,但如果您编写 ISO_C_Binding 接口(与我最初编写的不同)应该可以工作——“Fortran 95/2003 解释”一书说编译器将识别被调用的例程不是t 接收一个可分配的数组,并将执行复制入/复制出以匹配数组。

    附:我的猜测是,对于简单的可分配实际参数,不需要复制输入/复制输出。当编译器通过显式接口(可能是 ISO_C_Binding 接口)识别被调用例程的虚拟参数不是可分配的时,编译器应该能够从可分配的描述中提取指向实际数组的指针,并且将其作为参数传递。在某些情况下将需要复制入/复制出,例如指向非连续数组的指针,例如具有非单位跨度的指针(例如,指向元素 1、3、5、.. .)。但是没有任何接口,编译器可能会传递可分配数组的描述符,这不是 C 所期望的......

    【讨论】:

      【解决方案3】:

      real_normal 是 32 位还是 64 位浮点?如果将函数声明为 void cFunc(float*data) 会发生什么?

      【讨论】:

      • win32,在访问数据后出现运行时错误。
      【解决方案4】:

      REAL 可能默认为REAL*4,在这种情况下,您需要float* 而不是double*

      还要确保在使用之前对函数进行原型设计,否则 C 倾向于在没有理由不这样做的情况下自动将 floats 提升为 doubles。并确保您没有获取double,然后获取它的地址并将其“作为”float* 传递。

      【讨论】:

      • 我无法更改 fortran 代码。所以我必须采用我的 C 代码。使用浮动它也不起作用。
      • 例如使用 long double 我得到“浮点溢出”。 (我正在使用 VS 的英特尔编译器)。
      猜你喜欢
      • 2012-12-21
      • 2020-01-15
      • 2017-11-14
      • 1970-01-01
      • 1970-01-01
      • 2012-12-13
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      相关资源
      最近更新 更多