在C中分配内存用于Fortran可分配 [英] Allocating memory in C for a Fortran allocatable
问题描述
我们正试图在C ++中接管传统Fortran代码(+100,000行代码)的内存分配,因为我们使用C库在集群上分配和分配分布式内存。可分配变量在模块中定义。当我们调用使用这些模块的子程序时,索引似乎是错误的(移动一个)。然而,如果我们将相同的参数传递给另一个子例程,我们就得到了我们期望的结果。以下简单示例说明了此问题:
We are trying to take over the memory allocation of a legacy Fortran code (+100,000 lines of code) in C++, because we are using a C library for partitioning and allocating distributed memory on a cluster. The allocatable variables are defined in modules. When we call subroutines that use these modules the index seems to be wrong (shifted by one). However, if we pass the same argument to another subroutine we get what we expect. The following simple example illustrates the issue:
hello.f95:
hello.f95:
MODULE MYMOD
IMPLICIT NONE
INTEGER, ALLOCATABLE, DIMENSION(:) :: A
SAVE
END MODULE
SUBROUTINE TEST(A)
IMPLICIT NONE
INTEGER A(*)
PRINT *,"A(1): ",A(1)
PRINT *,"A(2): ",A(2)
END
SUBROUTINE HELLO()
USE MYMOD
IMPLICIT NONE
PRINT *,"A(1): ",A(1)
PRINT *,"A(2): ",A(2)
CALL TEST(A)
end SUBROUTINE HELLO
main.cpp
extern "C" int* __mymod_MOD_a; // Name depends on compiler
extern "C" void hello_(); // Name depends on compiler
int main(int args, char** argv)
{
__mymod_MOD_a = new int[10];
for(int i=0; i<10; ++i) __mymod_MOD_a[i] = i;
hello_();
return 0;
}
我们正在编译:
We are compiling with:
gfortran -c hello.f95; c++ -c main.cpp; c++ main.o hello.o -o main -lgfortran;
运行./main的输出为
Output from running ./main is
A(1): 1
A(2): 2
A(1): 0
A(2): 1
正如你可以看到A的输出是不同的,虽然两个子程序都打印了A(1)和A(2)。因此,HELLO似乎从A(0)而不是A(1)开始。这可能是因为ALLOCATE从来没有在Fortran中直接调用,所以它不知道A的边界。任何工作?
As you can see the output of A is different, though both subroutines printed A(1) and A(2). Thus, it seems that HELLO starts from A(0) and not A(1). This is probably due to that ALLOCATE has never been called directly in Fortran so that it is not aware of the bounds of A. Any work arounds?
推荐答案
Fortran数组哑变量总是从子程序中定义的下界开始。它们的下限在呼叫期间不被保留。因此, TEST()
中的参数 A
将始终从一个开始。如果您希望从 42
开始,您必须:
Fortran array dummy arguments always start at the lower bound defined in the subroutine. Their lower bound is not retained during the call. Therefore the argument A
in TEST()
will always start at one. If you wish it to start from 42
, you must do:
INTEGER A(42:*)
使用Fortran指针更好。
Regarding the allocation, you are playing with fire. It is much better to use Fortran pointers for this.
integer, pointer :: A(:)
然后可以通过
use iso_c_binding
call c_f_pointer(c_ptr, a, [the dimensions of the array])
其中 c_ptr
是 type(c_ptr)
与 void *
(也来自 iso_c_binding
)。
---编辑---
一旦我看到@Max la Cour Christensen实现了我上面的草图,我看到我误解了代码的输出。描述符确实错了,虽然我没有写任何明显的错误。上述解决方案仍然适用。
---Edit--- Once I see that @Max la Cour Christensen implemented what I sketched above, I see I misunderstood the output of your code. The descriptor was indeed wrong, though I didn't write anything plain wrong. The solution above still applies.
这篇关于在C中分配内存用于Fortran可分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!