本文介绍了如何将C ++中的2D数组传递给Fortran子例程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个小C ++程序,它将一个2-D数组(复数)传递给一个Fortran子程序,并接收它返回的值。我写了一个版本,它传递和接收1-D数组,这很好。 2-D版本不工作(我的真正目标是编写大尺寸的4-D版本,因此这些数组必须动态分配)。

I am writing a small C++ program which passes a 2-D array (of complex numbers) to a Fortran subroutine and receives it back filled with values. I wrote a version which passes and receives a 1-D array, and this works well. The 2-D version doesn't work (my true goal is to write a 4-D version with large dimensions - so these arrays have to be dynamically allocated).

我将发布我的工作代码和非工作代码,但首先注意,我被迫使用结构(简单的,只包含两个双打),因为Fortran似乎解释这些完全相同的方式,因为它自己的本机复数。这就是为什么我的1-D版本工作。出于同样的原因,我不认为这是一个复数问题。

I will post both my working code and non-working code, but first note that I was forced to use structs (simple ones, just containing two doubles) because Fortran seems to interpret these in exactly the same way as its own native complex numbers. This is why my 1-D version works. For the same reason, I don't think this is a 'complex number' issue.

这里是我的工作代码。将复数的1-D数组传递给Fortran子程序:

Here is my working code. Passing 1-D array of complex numbers to Fortran subroutine:

Fortran子程序:

The Fortran subroutine:

subroutine carray(A)
complex*16 A(2)

A(1) = cmplx(3,7)
A(2) = cmplx(9,5)

return
end

代码:

include <iostream>
include <complex>
using namespace std;

struct cpx{double r, i;};

extern"C"
{
   void carray_(struct cpx* A);
}

int main()
{
   struct cpx* A;
   A = new struct cpx [2];

   carray_(A);

   complex<double>* P;
   P = new complex<double> [2];

   for(x = 0; x < 2; x++)
   {
      real(P[x] = A[x].r;
      imag(P[x] = A[x].i;
   }

   cout << real(P[0]) << "\t" << imag(P[0]) << "\n";
   cout << real(P[1]) << "\t" << imag(P[1]) << "\n";

   return 0;
}

使用以下命令编译时无需投诉:

Compiling with the following commands works without complaint:

gfortran -c CarrayF.f
g++ -c CarrayC.cc
g++ -o Carray CarrayC.o CarrayF.o -lgfortran

所以只要我把(native)Fortran复数处理成两个双精度的结构,我可以把它们放入(非本地的)C ++复杂类型。Fortran子程序似乎是一个完美的快乐接收指针

So as long as I treat the (native) Fortran complex number like a struct of two doubles, I can put them into the (non-native) C++ complex type. The Fortran subroutine seems to be perfectly happy receiving a pointer where it expects an array. So far so good.

这是我的非工作尝试传递一个二维数组:

Here is my non-working attempt to pass a 2D array:

Fortran代码:

The Fortran code:

subroutine carray(A)
complex*16 A(2,2)

A(1,1) = cmplx(3,7)
A(1,2) = cmplx(9,5)
A(2,1) = cmplx(2,3)
A(2,2) = cmplx(4,9)

return
end

C ++代码:

include <iostream>
include <complex>
using namespace std;

struct cpx{double r, i;};

extern"C"
{
   void carray_(struct cpx** A);
}

int main()
{
   struct cpx** A;
   A = new struct cpx* [2];
   for(int x = 0; x < 2; x++)
   {
      A[x] = new struct cpx [2];
   }

   carray_(A);

   complex<double>** P;
   P = new complex<double>* [2];
   for(int x = 0; x < 2; x++)
   {
      P[x] = new complex<double> [2];
   }

   for(x = 0; x < 2; x++)
   {
      for(int y = 0; y < 2; y++)
      {
         real(P[x][y] = A[x][y].r;
         imag(P[x][y] = A[x][y].i;
      }
   }

   cout << real(P[0][0]) << "\t" << imag(P[0][0]) << "\n";
   cout << real(P[0][1]) << "\t" << imag(P[0][1]) << "\n";
   cout << real(P[1][0]) << "\t" << imag(P[1][0]) << "\n";
   cout << real(P[1][1]) << "\t" << imag(P[1][1]) << "\n";

   return 0;
}

这实际上是编译没有抱怨(与1-D版本相同的编译过程),但运行可执行文件产生一个立即分段错误,头痛使用两种语言在一起,调试器是没有帮助。

This actually compiles without complaint (same compilation procedure as for the 1-D version), but running the executable produces an immediate segmentation fault. Because of the headache of using two languages together, the debugger is not being helpful.

我有一个微不足道的错误在某个地方,我似乎没有超过任何数组边界。 Fortran子例程很乐意接收一个指针,但显然它不知道如何处理一个指针的指针。通常,Fortran只是处理数组名称,甚至对于多维数组,但我需要了解Fortran如何处理2D数组。

Have I made a trivial error somewhere? I don't seem to be exceeding any array bounds. The Fortran subroutine is happy to receive a pointer, but obviously it doesn't understand what to do with a pointer to a pointer. Ordinarily, Fortran would simply deal in terms of array names, even for multidimensional arrays, but I need to understand how Fortran deals with 2D arrays.

推荐答案

Fortran中的多维数组被存储为内存中的平面列主要数组。它们不是指向指针的指针,它们实际上只是一维数组,您必须对其进行一些额外的算术运算来计算数组索引。

Multidimensional arrays in Fortran are stored as flat column-major arrays in memory. They are not pointers to pointers—they're really just 1D arrays where you have to do some extra arithmetic to compute array indices.

从C ++传递数组的正确方法是这样的:

The correct way to pass the array from C++ is like this:

extern "C" void carray_(struct cpx *A);
...
struct cpx A[2*2];
carray_(A);

complex<double> P[2][2];
for(int i = 0; i < 2; i++)
{
    for(int j = 0; j < 2; j++)
    {
        // note order of indicies: A is column-major
        P[i][j] = std::complex<double>(A[j*2 + i].r, A[j*2 + i].i);
    }
}

这篇关于如何将C ++中的2D数组传递给Fortran子例程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 18:13
查看更多