2016-05-11 6 views
0

У меня есть один код fortran (gmf.f), который отлично работает, и я хочу называть его из c (tropo.c), поэтому я могу использовать выходы подпрограммы fortran в моем 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, я написал один образец после некоторого исследования на WEB. Что я боюсь, я не знаю, как назвать результаты fortran в 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 tropo.c

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

./solve

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

+1

Это не имеет особого отношения к C++. – molbdnilo

+1

Разве это не тот же вопрос, что и http://stackoverflow.com/questions/37147425/c-returning-fortran-results немного подобрали? –

+0

Вы должны отредактировать и улучшить свой старый вопрос. Не переставляйте то же самое, вы рискуете голосом и даже запретом. Обратите внимание, что удаленные вопросы относятся к вопросу о запрете. –

ответ

0

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

#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 

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

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

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

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

+0

Я думаю, что это, скорее всего, дубликат некоторого QA, хотя ... – roygvib

+0

Спасибо roygvib ... Ваш ответ хорошо работает ... Позже я меняю структуру fortran на функцию с функцией (dmjd, dlat, dlon, dhgt, zd) result (gmfh, gmfw) ", и он также работал с моим кодом c – noble334

+0

Хм, вам может потребоваться некоторое предостережение, чтобы получить несколько возвращаемых переменных из функции Fortran'; см. http://stackoverflow.com/questions/37120263/function-which-returns-multiple-values/ (хотя этот QA не связан с интерфейсом C-Fortran). Если необходимо, пожалуйста, подумайте о публикации другого вопроса (потому что это совсем другая тема, я думаю). – roygvib