在C中分配内存用于Fortran可分配 [英] Allocating memory in C for a Fortran allocatable

查看:220
本文介绍了在C中分配内存用于Fortran可分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正试图在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆