Fortran 中 REAL(KIND=real_normal) 的 C 等效类型是什么?
我在将数组从 Fortran 传递到 ac 函数时遇到问题: 在 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)
目前我收到运行时错误“Floating-点溢出”。在某些情况下,数组的元素是正确的。
I have a problem with passing of an array from Fortran to a c function:
In the fortran the array is defined as
REAL(KIND=real_normal) , DIMENSION(:), ALLOCATABLE :: array
call cFunc(array)
If define the cFunc as
void cFunc(double *data){...}
Than the data contains only "garbage" values. Where is the problem in this case? (with integers works this solution well).
thx.
EDIT:
My platform:
Compiler: VS 2008, Intel compiler 11 version
OS: Win7
EDIT 2:
I define the interface for the c-function like this (the code is reduced to one element, which makes problems, real function has more parameters):
interface c_interface
subroutine cFunc(array) bind (C, name = "cFunc")
use iso_c_binding
REAL(c_double), DIMENSION(*)::array
end subroutine cFunc
The memory in the fortran is allocated with
ALLOCATE (array(numberOfElements))
call cFunc(array)
At the moment i get an runtime error "Floating-point overflow". In some cases the array correct elements.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
片段
REAL(KIND=real_normal)
不是数据类型的完整标准规范。在您拥有的源代码中,必须有变量real_normal
的声明。我猜测它的声明是array
是 4 或 8 字节浮点数,但这只是一个猜测。array
并不是默认浮点数数组(Fortran 称为real
)。正如其他回答者之一所建议的,研究 Fortran 2003 的与 C 功能的互操作性。如果您的编译器没有实现这些功能,请放弃它并获取可以实现这些功能的编译器。
The fragment
REAL(KIND=real_normal)
is not a complete and standard specification of a datatype. Somehwere in the source you have there must be a declaration of the variablereal_normal
. I'd guess that it is declared such thatarray
is either 4- or 8-byte floating-point numbers, but that is only a guess. Whatarray
isn't is an array of default floating-point numbers (calledreal
by Fortran).As one of the other answerers has suggested, investigate the interoperability with C features of Fortran 2003. If your compiler doesn't implement these, ditch it and get a compiler that does.
@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 接收可分配数组并将执行复制入/复制出以匹配数组。
PS 我的猜测是,对于简单的可分配实际参数来说,复制输入/复制输出不是必需的。当编译器通过显式接口(可能是 ISO_C_Binding 接口)识别出被调用例程的虚拟参数不是可分配的时,编译器应该能够从可分配的描述中提取指向实际数组的指针,并且将其作为参数传递。在某些情况下会需要复制入/复制出,例如指向非连续数组的指针,例如具有非单位步长的指针(例如,指向元素 1, 3, 5, .. 的指针) .)。但是如果没有任何接口,编译器可能会传递可分配数组的描述符,这不是 C 所期望的......
@High Performance Mark's suggestions are very good, and I highly recommend the ISO_C_Binding of Fortran 2003 (supported by numerous Fortran compilers) for interoperability between Fortran and C -- there is a larger issue here that makes the ISO_C_Binding more useful: Fortran allocatable arrays are more complicated then ordinary arrays. If you "hack it" and directly pass a pointer to the C code, you are likely to pass a pointer to a Fortran internal structure describing the allocatable array rather than a pointer to the sequence of numeric values. Allocatable arrays aren't directly supported by the ISO_C_Binding, but should work if you write an ISO_C_Binding interface (unlike what I wrote originally) -- the book "Fortran 95/2003 explained" says that the compiler will recognize the the called routine isn't receiving an allocatable array and will perform copy-in/copy-out to match the arrays.
P.S. My guess is that copy-in/copy-out shouldn't be necessary for a simple allocatable actual argument. When the compiler recognizes via an explicit interface (which could be an ISO_C_Binding interface) that the dummy argument of the called routine is not an allocatable, the compiler should just be able to extract the pointer to the actual array from the description of the allocatable and pass that as the argument. Copy-in/copy out will be required in some cases, such as a pointer to a non-contiguous array, such as pointer with a non-unit stride (e.g., a pointer that points to elements 1, 3, 5, ...). But without any interface, the compiler will likely pass the descriptor of the allocatable array, which won't be what C is expecting....
real_normal
是 32 位还是 64 位浮点?如果将函数声明为void cFunc(float*data)
会发生什么?Is
real_normal
32-bit or 64-bit floating-point? What happens if you declare the function asvoid cFunc(float*data)
?REAL
可能默认为REAL*4
,在这种情况下,您需要float*
而不是double*
。还要确保在使用函数之前对其进行原型设计,否则 C 会在没有理由的情况下自动将
float
提升为double
。并确保您没有获取一个 double,然后获取它的地址并将其“作为”float* 传递。REAL
might default toREAL*4
in which case you want afloat*
instead ofdouble*
.Also make sure that you are prototyping the function before using it, otherwise C has a tendency to auto-promote
float
s todouble
s in the absence of a reason not to. And make sure that you aren't taking adouble
and then taking an address of it and passing it "as" afloat*
.