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

时间:2013-04-26 13:47:06

标签: c parameters fortran

假设我在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 :(得分: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

  

子程序exec(routine_c)bind(C,name =“exec_”)       使用iso_c_binding       隐含无

    abstract interface
        subroutine sub(a,b) bind(C)
          use iso_c_binding
          implicit none
          real(c_double),value :: a
          real(c_double) :: b
        end subroutine
    end interface

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

call c_f_procpointer(routine_c,routine)

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

结束子程序exec

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