从C代码调用Fortran子例程

时间:2016-05-11 08:45:02

标签: c fortran cygwin gfortran fortran-iso-c-binding

我有一个fortran代码(gmf.f)工作得很好,我想从c(tropo.c)调用它,所以我可以在我的c代码中使用fortran子程序的输出作为新变量。

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 solve gmf.o tropo.o

./解决

并将在屏幕上看到结果:gmfh和gmfw。

1 个答案:

答案 0 :(得分:0)

作为首发,请尝试以下修改。关键点在于,因为gmf()是Fortran subroutine(不是function),所以它不返回任何返回变量。因此,我们不需要编写result = gmf_(...);,而只需编写gmf_(...);。请注意,gmfhgmfw的值将由Fortran端的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

一些旁注:

  • AFAIK没有自动机制来检查C和Fortran之间的参数类型匹配的正确性。因此,请仔细检查原型中的类型声明,以便它们与Fortran例程中的类型完全匹配。不仅变量的类型(例如,integerreal,......)而且它们的种类(例如,real(xxx)double precision等)也非常重要。

  • 如果可能,请尝试在Fortran例程中使用implicit none,因为它可以更容易地检测到任何拼写错误或类型不匹配。

  • 代码运行后,请考虑使用iso_c_binding(特别是bind(C))来使界面更具可移植性。