Мы пытаемся взять на себя выделение памяти устаревшего кода Fortran (+100 000 строк кода) в C++, потому что мы используем библиотеку C для разделения и выделения распределенной памяти в кластере. Размещаемые переменные определяются в модулях. Когда мы вызываем подпрограммы, использующие эти модули, кажется, что индекс неправильный (смещен на единицу). Однако если мы передадим тот же аргумент другой подпрограмме, мы получим то, что ожидаем. Следующий простой пример иллюстрирует проблему:
привет.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 отличается, хотя обе подпрограммы вывели A(1) и A(2). Таким образом, кажется, что HELLO начинается с A(0), а не с A(1). Вероятно, это связано с тем, что ALLOCATE никогда не вызывался непосредственно в Fortran, поэтому он не знает о границах A. Любые обходные пути?
INTEGER A(*)
, всегда начинаются с 1, это не имеет ничего общего с их размещением. Здесь применяются правила передачи аргументов. - person Vladimir F   schedule 27.05.2014