首页 文章

如何将类型为external的参数从C传递给Fortran

提问于
浏览
0

假设我在Fortran中有以下子例程

subroutine exec(routine)

        implicit none

        external     :: routine
        real(kind=8) :: res

        call routine(2.0d0, res)
        print *, "Fortran Result: res = ", res

    end subroutine exec

该子例程接收外部例程作为参数 . 现在,假设这个例程是用C编写的,我还需要从C调用Fortran例程 exec . 像这样:

void op(double x, double *f) {
        *f = pow(x, 2);
    }

    void main() {
        exec_(op);
    }

我知道,如果不是传递一个外部子程序,而是传递一个整数,一个double或另一个传统类型,它会起作用,但是这个代码会返回分段错误 . 有没有办法将类型为external的参数从C传递给Fortran?

1 回答

  • 0

    这有效,你必须使用指针:

    void op(double *x, double *f) {
        *f = pow(*x, 2);
    }
    
    void main() {
        exec_(&op);
    }
    
    subroutine exec(routine)
    
        implicit none
    
        external     :: routine
        real(kind(1.d0)) :: res
    
        call routine(2.0d0, res)
        print *, "Fortran Result: res = ", res
    
    end subroutine exec
    

    不要使用 kind=8 它不会声明8字节真实,而是处理器相关类型,类型为8.即使旧的和非标准的 real*8 会更好 .

    但最好使用Fortran 2003 c互操作性和 iso_c_binding 模块:

    f.f90

    subroutine exec(routine_c)bind(C,name =“exec_”)使用iso_c_binding隐式无抽象接口
    子程序sub(a,b)bind(C)
    使用iso_c_binding
    隐含无
    real(c_double),value :: a
    real(c_double):: b
    结束子程序
    结束界面

    type(c_funptr),value :: routine_c
    real(c_double):: res
    procedure(sub),pointer :: routine

    调用c_f_procpointer(routine_c,routine)

    呼叫例程(2.0d0,res)
    print *,“Fortran结果:res =”,res
    结束子程序执行

    C.C

    #include <math.h>
    void op(double x, double *f) {
        *f = pow(x, 2.0);
    }
    
    int main() {
        extern void exec_(void (*) (double, double *));
        exec_(&op);
        return 0;
    }
    

    汇编:

    gfortran c.c f.f90 -Wall -g -fbacktrace -fcheck=all
    cc1: warning: command line option ‘-fbacktrace’ is valid for Fortran but not for C [enabled by default]
    cc1: warning: command line option ‘-fcheck=all’ is valid for Fortran but not for C [enabled by default]
     ./a.out 
     Fortran Result: res =    4.0000000000000000
    

相关问题