ISO_C_BINDING Calling C routine from Fortran (with doubles and arrays)

六月ゝ 毕业季﹏ 提交于 2019-12-18 07:25:11

问题


I posted a similar question few weeks ago (iso_c_binding calling C routine with pointers from Fortran with arrays) and I found a solution to my problem. Now I modified few things and I am having some problems again. In the following a simplified version of my problem.

I have a main program in 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

Which use a subroutine containing the interface for the C routine:

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 

and this is the C routine:

#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;

}

If I compile and run the program, this is what I get:

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

Notice that before putting the variable "spin" everything was working. It could read the input array, make the opration, and give the right output.

Now that I added ths variable, there are some problems for the C routine in reading what I'm passing and I cannot understand what's wrong. Any suggestion ?

(Consider that in the real case I'm going to pass several variables as well as 2 input and 2 output arrays with dimension 4).

Many thanks in advance!!


回答1:


Change your interface to:

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 

Your C function takes a double rather than double* so you need to pass the scalar with the value attribute so that the Fortran knows to pass by value rather than its default pass by reference.

With this small change (and some minor changes to your C to actually print the values of m and phi) this is the output of your example code:

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


来源:https://stackoverflow.com/questions/26678961/iso-c-binding-calling-c-routine-from-fortran-with-doubles-and-arrays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!