c-在C中为可分配的Fortran分配内存

我们正在尝试接管C中遗留的Fortran代码(100,000行代码)的内存分配,因为我们正在使用C库在集群上分区和分配分布式内存.可分配变量在模块中定义.当我们调用使用这些模块的子例程时,索引似乎是错误的(移位了一个).但是,如果将相同的参数传递给另一个子例程,则会得到期望的结果.以下简单示例说明了该问题:

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;
}

我们正在编译:

gfortran -c hello.f95; c++ -c main.cpp; c++ main.o hello.o -o main -lgfortran;

正在运行的./main的输出是

 A(1):            1
 A(2):            2
 A(1):            0
 A(2):            1

如您所见,尽管两个子例程都打印了A(1)和A(2),但A的输出却不同.因此,似乎HELLO从A(0)开始,而不是A(1).这可能是由于从未在Fortran中直接调用过ALLOCATE,所以它不知道A的范围.有什么解决方法吗?

解决方法:

Fortran数组伪参数始终从子例程中定义的下限开始.在通话期间不会保留其下限.因此,TEST()中的参数A将始终从1开始.如果希望从42开始,则必须执行以下操作:

INTEGER A(42:*)

关于分配,您在玩火.为此,最好使用Fortran指针.

integer, pointer :: A(:)

然后,您可以将数组设置为指向C缓冲区,方法是

use iso_c_binding

call c_f_pointer(c_ptr, a, [the dimensions of the array])

其中c_ptr的类型为(c_ptr),可与void *互操作,后者也来自iso_c_binding.

– -编辑 – –
一旦看到@Max la Cour Christensen实现了我上面概述的内容,我就会误解您的代码输出.描述符确实是错误的,尽管我没有写任何明显的错误.上面的解决方案仍然适用.

上一篇:python – zgeev()LAPACK的结果不正确/不一致


下一篇:linux – 执行命令行并返回命令输出