Как передать массив C_FLOAT в подпрограмму Fortran

В Fortran у меня есть массив C_FLOAT, который объявлен как входной аргумент:

SUBROUTINE Main(n,myCArray)  BIND(C, NAME = 'Main')
INTEGER(C_INT),         INTENT(IN   ) :: n
REAL(C_FLOAT),          INTENT(INOUT), dimension(n) :: myCArray
    CALL PrintTheArray(n,myCArray)
END SUBROUTINE MAIN

Как написано в теле подпрограммы Main, я хочу передать myCArray другой подпрограмме следующим образом:

SUBROUTINE PrintTheArray(n,theCArray)
INTEGER(C_INT),         INTENT(IN   ) :: n
REAL(C_FLOAT),          INTENT(INOUT), dimension(n) :: theCArray
print *, theCArray(1), theCArray(2)
END SUBROUTINE PrintTheArray

Делая это, я никогда не печатаю правильные значения массива. Однако, если я распечатаю значения в подпрограмме Main(), значения будут правильными. Что не так и как я могу это исправить?


Действительно, нет проблем с передачей массива C_FLOAT в Fortran. Так что вопрос неверный. Я привожу здесь минимальный, полный и проверяемый пример (я использую Ubuntu, GNU Fortran (GCC) 6.3.0, gcc (GCC) 6.3.0):

Код Fortran с именем файла FORTRANFunc.f90

MODULE TEST
USE, INTRINSIC :: ISO_C_Binding
  IMPLICIT NONE
contains
subroutine CALLFORTRAN(n,myArray) BIND (C, NAME = 'CALLFORTRAN')
  INTEGER(C_INT),  INTENT(IN   )  :: n
  REAL(C_FLOAT),   INTENT(IN   )  :: myArray(n)
  CALL PRINTARRAY(n,myArray)
end subroutine CALLFORTRAN

subroutine PRINTARRAY(n, myArray)
  INTEGER(C_INT),  INTENT(IN   )  :: n
  REAL(C_FLOAT),   INTENT(IN   )  :: myArray(n)
  print *, myArray(1), myArray(2)
end subroutine PRINTARRAY
END MODULE TEST

Код C с именем файла main.c

#include <stdio.h>
#include <stdlib.h>
extern void CALLFORTRAN(int* n, float* myArray);

int main()
{
   int n=2;
   float*  myArray = (float*) malloc(2);
   myArray[0] = 0.5;
   myArray[1] = 1.5;
   CALLFORTRAN(&n,myArray);
   return 0;
}

вы можете скомпилировать с:

gfortran -c FORTRANFunc.f90
gfortran main.c FORTRANFunc.o -o test

затем вы выполняете с:

./test

Результат должен быть:

  0.500000000       1.50000000

person Chengyu Wang    schedule 08.08.2017    source источник
comment
Можете ли вы создать для нас минимально воспроизводимый пример?   -  person francescalus    schedule 08.08.2017
comment
В самом деле, что же тогда он печатает, когда печатает неправильные значения? У вас вообще есть правильные значения внутри Main()? Необходимо подробное описание проблемы и минимально воспроизводимый пример.   -  person Vladimir F    schedule 08.08.2017
comment
У меня такое чувство, что проблема заключается в коде C. Обычно нет проблем с передачей массивов C_FLOAT между подпрограммами Fortran.   -  person Matt P    schedule 08.08.2017
comment
Вторая строка обычно USE ISO_C_BINDING. C передается по ссылке или значению?   -  person Holmz    schedule 09.08.2017
comment
@Holmz Для use iso_c_binding нет абсолютно никакой причины, если он уже используется в каком-то модуле выше. use iso_c_binding никоим образом НЕ изменяет соглашение о вызовах (передача по значению/ссылке).   -  person Vladimir F    schedule 09.08.2017
comment
Почему ответ является частью вопроса?   -  person Chintan Pathak    schedule 26.08.2017


Ответы (1)


Я не могу воспроизвести проблему с gfortran 5.4.0 (полная версия: GNU Fortran (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609) или IBM XL Fortran. Может ли это быть проблемой с новым gfortran?

$ gfortran -c FORTRANFunc.f90
$ gcc -c main.c
$ gfortran FORTRANFunc.o main.o -o test
$ ./test
  0.500000000       1.50000000
$

Кроме того, имеет ли значение замена dimension(n) на dimension(*)?

person Rafik Zurob    schedule 09.08.2017
comment
На самом деле, вопрос был неправильным, как разъяснено выше. Так что совершенно нормально передавать массивы C_FLOAT в FORTRAN. Изменение {dimension(n)} на {dimension(*)} также правильно. - person Chengyu Wang; 10.08.2017