Как передать двумерный массив на C ++ в подпрограмму Fortran?

Я пишу небольшую программу на C ++, которая передает двумерный массив (комплексных чисел) в подпрограмму Fortran и получает его обратно, заполненный значениями . Я написал версию, которая передает и получает одномерный массив, и это хорошо работает. Двухмерная версия не работает (моя истинная цель - написать четырехмерную версию с большими размерами, поэтому эти массивы должны быть размещены динамически).

Я опубликую как свой рабочий, так и нерабочий код , но сначала обратите внимание, что я был вынужден использовать структуры (простые, просто содержащий два двойных), потому что Fortran, кажется, интерпретирует их точно так же, как свои собственные комплексные числа. Вот почему моя одномерная версия работает. По той же причине я не думаю, что это проблема «комплексных чисел».

Вот мой рабочий код. Передача одномерного массива комплексных чисел в подпрограмму Fortran:

Подпрограмма Fortran:

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

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

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

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

Компиляция со следующими командами работает без жалоб:

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

Итак, пока я использую (родной ) Комплексное число Фортрана как структура из двух двойников, я могу поместить их в (неродной) сложный тип C ++. Подпрограмма Fortran, кажется, вполне довольна получением указателя там, где она ожидает массив. Пока все хорошо.

Вот моя нерабочая попытка передать 2D-массив:

Код Fortran:

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 версии), но запуск исполняемого файла вызывает немедленную ошибку сегментации. Из-за головной боли от одновременного использования двух языков отладчик бесполезен.

Я где-то допустил тривиальную ошибку? Кажется, я не превышаю никаких границ массива. Подпрограмма Fortran рада получить указатель, но, очевидно, не понимает, что делать с указателем на указатель. Обычно Фортран просто работает с именами массивов, даже для многомерных массивов, но мне нужно понимать, как Фортран работает с 2D-массивами.

5
задан ChrisF 8 September 2011 в 19:23
поделиться