Как Фортран возвращает массивы?

Подпрограмме Rule_Tn в библиотеке Fortran CUBPACK требуется параметр Integrand, описывающий интегрированную векторную функцию. Это

INTERFACE 
   FUNCTION Integrand(NF,X) RESULT(Value)
      USE Precision_Model
      INTEGER,                       INTENT(IN)  :: NF
      REAL(KIND=STND), DIMENSION(:), INTENT(IN)  :: X
      REAL(KIND=STND), DIMENSION(NF)             :: Value
   END FUNCTION Integrand
END INTERFACE

Поскольку я хочу вызвать Rule_Tn из кода C, мне нужно определить тип функции в C, точно соответствующий этому интерфейсу выше. Таким образом, я попытался выяснить, как функция Fortran возвращает массивы. Сначала я предположил, что следующая подпись C

void Integrand(double* value, const int* nf, const int* x);

совпадает с интерфейсом выше. Но далеко не так! У меня segfault. И я уже тестировал, что тип double соответствует типу REAL(KIND=STND), STND выходит из модуля Precision_Model.

Теперь кто-нибудь может сказать мне, какая подпись правильная? Я использую компиляторы GNU Fortran и C.


person phlipsy    schedule 19.08.2010    source источник


Ответы (1)


См. документацию GNU. Похоже, вы указали аргументы в другом порядке между Фортраном и C. Попробуйте поставить value последним в прототипе C.

Кроме того, в строке FUNCTION отсутствует bind(C).

person Potatoswatter    schedule 19.08.2010
comment
Дело не в этом, значение STND определяется в модуле Precision_Model, и я уже проверял, что REAL(KIND=STND) соответствует double. Возникает вопрос: какая сигнатура C соответствует этому интерфейсу? - person phlipsy; 19.08.2010
comment
@phlipsy: тогда вы можете изменить эту формулировку. Обновление ответа. - person Potatoswatter; 19.08.2010
comment
Хорошо, я повторил эту часть своего вопроса. - person phlipsy; 19.08.2010
comment
@Potatoswatter: Конечно, исходный код CUBPACK открыт, и я могу изменить его в соответствии со своими потребностями (используя модуль iso_c_binding, как вы предложили), но сначала я хочу обойтись без каких-либо изменений в коде Fortran. - person phlipsy; 19.08.2010
comment
@philpsy: Я настоятельно рекомендую использовать привязку ISO C как простой и переносимый способ подключения C и Fortran. Если вы не хотите изменять исходный исходный код Fortran, вы можете написать небольшую процедуру интерфейса Fortran, которая вызывается вашим C-кодом с использованием привязки ISO C, и которая вызывает исходную процедуру Fortran с исходным интерфейсом (не ISO C Переплет). - person M. S. B.; 19.08.2010
comment
@MSB: способ, которым Фортран возвращает массивы, не стандартизирован? В этом случае было бы лучше всего использовать эти привязки ISO C. - person phlipsy; 19.08.2010
comment
@phipsy: Нет, стандарт языка не определяет соглашения о вызовах Фортрана. Это считается выбором реализации поставщиком компилятора. Если вы используете привязку ISO C, тогда языковой стандарт требует согласованности между компиляторами Fortran и C одного и того же поставщика. (Действительно, Intel ifort и gcc согласованы, хотя и от разных авторов.) И ваш код будет переносимым на пару компиляторов другого производителя. Кроме того, я не уверен, что привязка ISO C поддерживает возвращаемые значения функции массива. Возможно, вам придется сделать вашу процедуру склейки подпрограммой. - person M. S. B.; 19.08.2010
comment
@MSB: Ты прав! Я тестировал BIND(C) на функции с массивом значений: gfortran отклонил ее. Спасибо за информацию! - person phlipsy; 20.08.2010