几周前我发布了一个类似的问题(iso_c_binding calling C routine with pointers from Fortran with arrays),我找到了解决问题的方法。 现在我修改了一些东西,我又遇到了一些问题。 以下是我的问题的简化版本。
我在fortran有一个主程序:
program main_dummy
! compile: gcc -c dummy_trace.c
! f95 raytracing.f90 main_dummy.f90 dummy_trace.o -o main
use, intrinsic :: ISO_C_BINDING
use raytracing
implicit none
!real(kind=8) :: x_in(4), x_fin(4)
real(C_DOUBLE), dimension(0:3) :: x_in, x_fin
real(C_DOUBLE) :: spin
integer :: rt_ok
x_in = (/1,2,3,4/)
x_fin = (/0,0,0,0/)
spin = 0.7
write(*,*)'x_in, x_fin before = ', x_in, x_fin
rt_ok = photon_trace(spin,x_in,x_fin)
write(*,*)'return rt = ', rt_ok
write(*,*)'x_in, x_fin after = ', x_in, x_fin
end program main_dummy
使用包含C例程接口的子例程:
module raytracing
Interface
integer (C_INT) function photon_trace(BHsp, x_init, x_final) &
bind(C, name='photon_trace')
use , intrinsic :: ISO_C_BINDING
implicit none
real(C_DOUBLE) :: BHsp, x_init(4), x_final(4)
end function photon_trace
end interface
end module raytracing
这是C例程:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
#undef I
int photon_trace(double BHsp, double x_init[4], double x_final[4])
//***************************************************
{
printf("BHsp %f\n", BHsp);
double r,m,t,phi;
t = x_init[0];
r = x_init[1];
m = x_init[2];
phi = x_init[3];
printf("t0 %f\n", t);
printf("r0 %f\n", r);
printf("m0 %f\n", t);
printf("phi0 %f\n", r);
t=t+1.0;
r=r+1.0;
m=m+1.0;
phi=phi+1.0;
printf("t1 %f\n", t);
printf("r1 %f\n", r);
printf("m1 %f\n", t);
printf("phi1 %f\n", r);
x_final[0] = t;
x_final[1] = r;
x_final[2] = m;
x_final[3] = phi;
return 0;
}
如果我编译并运行程序,这就是我得到的:
x_in,x_fin before = 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
BHsp 0.000000
t0 0.700000
r0 0.000000
m0 0.700000
phi0 0.000000
t1 1.700000
r1 1.000000
m1 1.700000
phi1 1.000000
return rt = 0
x_in,x_fin after = 1.6999999880790710 1.0000000000000000 1.0000000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
请注意,在将变量“旋转”之前,一切正常。它可以读取输入数组,进行操作,并给出正确的输出。
现在我添加了变量,在读取我传递的内容时,C例程存在一些问题,我无法理解错误。 有什么建议吗?
(考虑到在实际情况下,我将传递几个变量以及2个输入和2个输出数组,尺寸为4)。
非常感谢提前!!
答案 0 :(得分:5)
将您的界面更改为:
module raytracing
Interface
integer (C_INT) function photon_trace(BHsp, x_init, x_final) &
bind(C, name='photon_trace')
use , intrinsic :: ISO_C_BINDING
implicit none
real(C_DOUBLE) :: x_init(4), x_final(4)
real(c_double), value :: BHsp
end function photon_trace
end interface
end module raytracing
你的C函数需要double
而不是double*
所以你需要传递带有value
属性的标量,以便Fortran知道传递值而不是默认值传递参考
通过这个小小的更改(以及对C实际打印m
和phi
的值的一些细微更改),这是示例代码的输出:
% ./main
x_in, x_fin before = 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
BHsp 0.700000
t0 1.000000
r0 2.000000
m0 3.000000
phi0 4.000000
t1 2.000000
r1 3.000000
m1 4.000000
phi1 5.000000
return rt = 0
x_in, x_fin after = 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000