Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从C包装器调用FORTRAN函数_C_Fortran_Fortran77 - Fatal编程技术网

从C包装器调用FORTRAN函数

从C包装器调用FORTRAN函数,c,fortran,fortran77,C,Fortran,Fortran77,我是这方面的新手,但我需要从C访问一些旧的Fortran 77函数。 如果可能的话,我不想修改Fortran代码,我更愿意编写一个包装器来从C调用Fortran函数。我希望得到一个最小的工作示例(在Linux上)。我所做的: 在文件somefunction.f中: REAL*8 FUNCTION MYFUNC(ZZ) IMPLICIT NONE REAL*8 ZZ, T1 T1 = ZZ + 1.0D0 MYFUNC = T1 RETU

我是这方面的新手,但我需要从C访问一些旧的Fortran 77函数。 如果可能的话,我不想修改Fortran代码,我更愿意编写一个包装器来从C调用Fortran函数。我希望得到一个最小的工作示例(在Linux上)。我所做的:

在文件somefunction.f中:

REAL*8 FUNCTION MYFUNC(ZZ)
      IMPLICIT NONE
      REAL*8 ZZ, T1
      T1 = ZZ + 1.0D0
      MYFUNC = T1
      RETURN
      END
使用
gfortran-csomefunction.f-osomefunction.o
编译

在文件debug.c中:

#include <stdio.h>

double cfunc(double x) {
    double result = myfunc_( &x );
    return result;
}
int main() {
    double test = cfunc(3.0);
    printf(" %.15f ",test);
}
#包括
双cfunc(双x){
双重结果=myfunc_x(&x);
返回结果;
}
int main(){
双重测试=cfunc(3.0);
printf(“%.15f”,测试);
}
使用
gcc-cdebug.c-odebug.o
编译

然后我给出了
gcc debug.o somefunction.o
/a.out

然而,我得到的不是3+1=4,而是无意义的数字。我如何纠正这个问题


附言:如果这个问题解决了,我的实际功能会更复杂一些:

  • 如果要将MYFUNC替换为类型
    COMPLEX*16函数MYFUNC(ZZ)
    ,并且ZZ也是一个复合体,我应该做什么更改

  • 如果MYFUNC调用了一些内置的Fortran函数,比如CDLOG(ZZ),会怎么样

  • 如果它访问一个公共块呢?这也能容纳吗


  • 好的,仅供参考,正如@IanBush所说,C程序应该声明myfunc的返回类型

    #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);
    }
    
    #包括
    双myfunc_u2;(双*);
    双cfunc(双x){
    双重结果=myfunc_x(&x);
    返回结果;
    }
    int main(){
    双重测试=cfunc(3.0);
    printf(“%.15f”,测试);
    }
    
    除了返回类型之外,您还需要注意Fortran过程名称被破坏成从C访问的符号的方式。没有标准,它完全取决于Fortran编译器和平台,因此如果您想要可移植性,您必须使用一些配置时间检测和宏

    例如,需要从C调用Fortran
    MYFUNC()
    ,如下所示:

    • Windows上英特尔Fortran下的MYFUNC()
    • IBM XL Fortran(
      xlf
      下的
      myfunc()
    • 在大多数其他情况下(包括Windows上的GNU Fortran),myfunc_u3;()
    (当Fortran例程位于模块中时,它会变得更加复杂,因为模块和
    \u MOD\u
    \u mp\u
    等会在名称前面加上损坏的前缀。)


    现代的Fortran解决方案是在Fortran端声明一个
    bind(C)
    例程,这将关闭这种混乱(或者您可以指定一个显式的绑定名称)。

    您是否在C中的任何位置声明myfunc的返回类型?您是对的,这就是问题所在。谢谢对于其他要点的任何提示,我们也将不胜感激@克雷格斯特伊:不,不是。Real*8不是也从来不是标准Fortran的一部分,因此它的行为是由实现定义的,并且有一些编译器不支持Real*8。相反,应该使用标准定义的种类机制。另请看回答这个问题的最佳方法是Fortran的标准定义方式与C的接口。@IanBush我没有说这是一个标准,只是它已经存在了几十年。fortran是一种后缘语言。编写新代码的唯一原因是与传统的科学库接口[这些库可能有数百万行使用
    real*8
    ]的代码]。
    real*8
    的使用比
    kind
    早至少二十年。因此,每一个需要相关的可靠fortran编译器都将支持
    real*8
    。而且,
    real*8xs
    real(KIND=8)::xs更为紧凑,因此它因其所需/使用的东西简洁而获胜。而且,F2008允许使用更好的
    REAL64
    。您已经使用fortran 77进行了标记,但是如果可以选择在fortran端编写包装器,我强烈建议使用fortran 2003提供的
    iso_c_binding
    模块:a)它定义了保证与其c对应项匹配的数据类型(=无需猜测
    real*8
    是否真的是
    double
    ,等等),以及b)a
    bind(c,name=“foo”)
    函数在c中有明确定义的签名和符号名称(
    foo(…)
    保证按预期工作)。简言之,它将带您走出泥泞的实现定义行为区域,进入符合标准的C/fortran的定义良好的领域。