Я пишу небольшую программу на C ++, которая передает двумерный массив (комплексных чисел) в подпрограмму Fortran и получает ее обратно, заполненную значениями. Я написал версию, которая передает и получает 1-D массив, и это работает хорошо. Двухмерная версия не работает (моя настоящая цель - написать четырехмерную версию с большими размерами, поэтому эти массивы нужно распределять динамически).
Я опубликую и мой рабочий код, и нерабочий код, но сначала обратите внимание, что я был вынужден использовать структуры (простые, содержащие только два типа double), потому что Fortran, похоже, интерпретирует их точно так же, как и свой собственный сложные числа. Вот почему моя 1-D версия работает. По той же причине, я не думаю, что это проблема «комплексного числа».
Вот мой рабочий код. Передача 1-D массива комплексных чисел в подпрограмму 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 ++. Подпрограмма на Фортране, кажется, совершенно счастлива, получив указатель, где она ожидает массив. Пока все хорошо.
Вот моя нерабочая попытка передать массив 2D:
Код Фортрана:
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 рада получить указатель, но, очевидно, она не понимает, что делать с указателем на указатель. Обычно, Fortran будет просто иметь дело с именами массивов, даже для многомерных массивов, но мне нужно понять, как Fortran работает с 2D-массивами.