Вызов подпрограмм Fortran из кода C

У меня есть один код fortran (gmf.f), который отлично работает, и я хочу вызвать его из c (tropo.c), чтобы использовать выходные данные подпрограммы fortran в моем коде c в качестве новых переменных.

subroutine gmf (dmjd,dlat,dlon,dhgt,zd,gmfh,gmfw)

C     This subroutine determines the Global Mapping Functions GMF

C     input data
C     ----------
C     dmjd: modified julian date   (real)
C     dlat: ellipsoidal latitude in radians  (real)
C     dlon: longitude in radians      (real)
C     dhgt: height in m                  (real)
C     zd:   zenith distance in radians        (real)
C
C     output data
C     -----------
C     gmfh: hydrostatic mapping function      (real)
C     gmfw: wet mapping function              (real)
C
C     Johannes Boehm, 2005 August 30
C     Rev. Boehm 21 July 2011: latitude -> ellipsoidal latitude
C

      implicit double precision (a-h,o-z)

... ... ... ... После некоторых математических вычислений в результате я получаю результаты gmfh и gmfw.

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

 #include<stdio.h>
  int main(int argc, char **argv) {




 double gmf_(double *dmjd, double *dlat, double *dlon, double *dhgt, double *zd, double *gmfh, double *gmfw);

 double dmjd=53120;
  double dlat=38.25;
  double dlon=42.25;
  double dhgt=700.25;
  double zd=60.0;


 ??? double result???? = gmf_(&dmjd, &dlat, &dlon, &dhgt, &zd, &gmfh, &gmfw);

  return;
  }

наконец я выполню в cygwin

gfortran -c gmf.f

gcc -c тропо.с

gfortran -o решить gmf.o tropo.o

./решить

и увидите результаты на экране: gmfh и gmfw.


person noble334    schedule 11.05.2016    source источник
comment
Это не имеет ничего общего с C++.   -  person molbdnilo    schedule 11.05.2016
comment
Разве это не тот же вопрос, что и stackoverflow.com/questions/37147425/ немного прибрался ?   -  person High Performance Mark    schedule 11.05.2016
comment
Вы должны отредактировать и улучшить свой старый вопрос. Не делайте репост такого же, рискуете получить дон-голоса и даже бан. Обратите внимание, удаленные вопросы засчитываются в бан вопросов.   -  person Vladimir F    schedule 11.05.2016
comment
Но gmf_ точно не возвращает двойника. Она ничего не возвращает на Фортране и, следовательно, ничего не возвращает на C. Сначала вы должны понять, как работает подпрограмма и что делают аргументы (параметры), и только после этого вы можете использовать ее на C. Документация в коде Fortran четко указывает, какие аргументы являются выходными данными.   -  person Vladimir F    schedule 11.05.2016
comment
Кстати, публикация кода в 2005 и 2011 годах, который начинается с implicit double precision, является почти нарушением.   -  person Vladimir F    schedule 11.05.2016


Ответы (1)


Для начала попробуйте следующие модификации. Ключевым моментом является то, что, поскольку gmf() является Fortran subroutine (а не function), он ничего не возвращает в качестве возвращаемой переменной. Поэтому нам не нужно писать result = gmf_(...);, а просто писать gmf_(...);. Обратите внимание, что значения gmfh и gmfw будут изменены непосредственно gmf() на стороне Фортрана, потому что они передаются указателями.

#include <stdio.h>

// Use "void" here because gmf() is a subroutine (with no return variable).
void gmf_ (double *dmjd, double *dlat, double *dlon,
           double *dhgt, double *zd,
           double *gmfh, double *gmfw);

int main()
{
    double dmjd = 1.0, dlat = 2.0, dlon = 3.0,
           dhgt = 4.0, zd   = 5.0;

    double gmfh, gmfw;

    // Call the Fortran routine. No need to write "result = gmf_(...)".
    // Instead, the values of gmfh and gmfw will be modified directly by gmf().
    gmf_ ( &dmjd, &dlat, &dlon, &dhgt, &zd, &gmfh, &gmfw );

    printf( "gmfh = %15.8f\n", gmfh );
    printf( "gmfw = %15.8f\n", gmfw );

    return 0;
}

Если вы используете более простую версию gmf(), например,

      subroutine gmf ( dmjd, dlat, dlon, dhgt, zd, gmfh, gmfw )

C     input data  : dmjd, dlat, dlon, dhgt, zenith
C     output data : gmfh, gmfw

c     implicit double precision (a-h,o-z)    !! this is not recommended...
      implicit none
      double precision :: dmjd, dlat, dlon, dhgt, zd, gmfh, gmfw

      gmfh = dmjd + dlat + dlon + dhgt
      gmfw = zd * 10.0d0
      end

(здесь gmf.f предполагается фиксированным форматом), получаем

gmfh =     10.00000000
gmfw =     50.00000000

Некоторые примечания:

  • Насколько я знаю, нет автоматического механизма для проверки правильности соответствия типов аргументов между C и Fortran. Поэтому, пожалуйста, очень внимательно проверяйте объявления типов в прототипе, чтобы они точно соответствовали объявлениям в подпрограммах Фортрана. Критически важны не только типы переменных (например, integer, real,...), но и их виды (например, real(xxx) или double precision и т. д.).

  • Если возможно, попробуйте использовать implicit none в подпрограммах Фортрана, потому что это значительно упрощает обнаружение любых опечаток или несоответствия типов.

  • После запуска кода рассмотрите возможность использования iso_c_binding (особенно bind(C)), чтобы сделать интерфейс более переносимым.

person roygvib    schedule 11.05.2016
comment
Спасибо, roygvib ... Ваш ответ работает хорошо ... Позже я изменил свою структуру фортрана, чтобы она функционировала с функцией (dmjd, dlat, dlon, dhgt, zd) result (gmfh, gmfw), и она также работала с моим кодом c - person noble334; 11.05.2016
comment
Хм, вам может понадобиться некоторая осторожность, чтобы получить несколько возвращаемых переменных из Fortran function; см. stackoverflow.com/questions/37120263/ (хотя этот QA не касается интерфейса C-Fortran). Если необходимо, рассмотрите возможность публикации другого вопроса (потому что, я думаю, это совсем другая тема). - person roygvib; 11.05.2016