Вызов функции FORTRAN из оболочки C - PullRequest
3 голосов
/ 19 марта 2020

Я новичок в этом, но мне нужно получить доступ к некоторым старым функциям Fortran 77 с C. Я не хочу изменять код Fortran, если это возможно, я действительно предпочел бы написать обертку для вызова функций Fortran из C. Я надеюсь получить минимальный рабочий пример (на Linux). Что я сделал:

В файле somefunction.f:

REAL*8 FUNCTION MYFUNC(ZZ)
      IMPLICIT NONE
      REAL*8 ZZ, T1
      T1 = ZZ + 1.0D0
      MYFUNC = T1
      RETURN
      END

скомпилировано с gfortran -c somefunction.f -o somefunction.o.

В файле отладки. c:

#include <stdio.h>

double cfunc(double x) {
    double result = myfunc_( &x );
    return result;
}
int main() {
    double test = cfunc(3.0);
    printf(" %.15f ",test);
}

скомпилировано с gcc -c debug.c -o debug.o.

Затем я даю gcc debug.o somefunction.o и ./a.out.

Однако вместо 3 + 1 = 4 я получаю бессмысленные числа. Как я могу исправить это?


PS: Если это решено, реальные функции у меня немного сложнее:

  1. Что я должен изменить, если MYFUN C должен был быть вместо типа COMPLEX*16 FUNCTION MYFUNC(ZZ) с ZZ также комплексным?

  2. Что, если MYFUN C вызвал некоторую встроенную функцию на Фортране, скажем, CDLOG (ZZ )?

  3. А что, если он обращается к общему блоку? Это тоже можно разместить?

Ответы [ 2 ]

3 голосов
/ 20 марта 2020

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

Например, Fortran MYFUNC() должен быть вызывается из C как:

  • MYFUNC() под Intel Fortran на Windows
  • myfunc() под IBM XL Fortran (xlf)
  • myfunc_() в большинстве других случаев (включая GNU Fortran на Windows)

(Это становится еще сложнее, когда в модуле находится процедура Fortran, потому что тогда искаженному имени предшествует модуль и _MOD_, _mp_, et c.)

Современное решение на Фортране состоит в том, чтобы объявить подпрограмму bind(C) на стороне Фортрана, которая отключает это искажение (или вы можете указать явное обязательное имя).

2 голосов
/ 19 марта 2020

ОК, просто для справки, как сказал @ IanBu sh, программа C должна была объявить тип возврата myfun c,

#include <stdio.h>

double myfunc_(double*);

double cfunc(double x) {
    double result = myfunc_( &x );
    return result;
}
int main() {
     double test = cfunc(3.0);
     printf(" %.15f ",test);
}
...