ISO_C_BINDING从Fortran调用C例程(带有双精度和数组)

时间:2014-10-31 16:09:32

标签: fortran fortran-iso-c-binding

几周前我发布了一个类似的问题(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)。

非常感谢提前!!

1 个答案:

答案 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实际打印mphi的值的一些细微更改),这是示例代码的输出:

% ./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