假设我在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?
答案 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