ISO_C_BINDING从Fortran调用C例程(使用双精度和数组) [英] ISO_C_BINDING Calling C routine from Fortran (with doubles and arrays)

查看:240
本文介绍了ISO_C_BINDING从Fortran调用C例程(使用双精度和数组)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几周前我发布了一个类似的问题( iso_c_binding使用来自Fortran与数组的指针调用C例程)),我找到了解决我的问题的方法。
现在我修改了几件事情,并且再次遇到一些问题。
下面是我的问题的简化版。



我在fortran中有一个主程序:

  program main_dummy 
!编译:gcc -c dummy_trace.c
! f95 raytracing.f90 main_dummy.f90 dummy_trace.o -o main
use,intrinsic :: ISO_C_BINDING
使用raytracing

隐式无

!real( 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


结束程序main_dummy


















$ b $ 模块raytracing
接口
整数(C_INT)函数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 )
结束函数photon_trace
结束接口
结束模块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 \\\
,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 \\\
,t);
printf(r0%f \\\
,r);
printf(m0%f \ n,t);
printf(phi0%f\\\
,r);

t = t + 1.0;
r = r + 1.0;
m = m + 1.0;
phi = phi + 1.0;

printf(t1%f \\\
,t);
printf(r1%f \\\
,r);
printf(m1%f \\\
,t);
printf(phi1%f \\\
,r);

x_final [0] = t;
x_final [1] = r;
x_final [2] = m;
x_final [3] = phi;

返回0;




$ b $ p
$ b如果我编译并运行这个程序,得到:

x_in,x_fin before = 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000

BHsp 0.000000



0.700000
$ b $ r 0.000000

0.700000
p>

phi0 0.000000

t1 1.700000

1.00 1.00



1.700000



return rt = 0

x_in,x_fin后= 1.6999999880790710 1.00000000000000 1.00 1.00000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000

请注意,变量旋转一切正常。它可以读取输入数组,进行操作并输出正确的结果。

现在我添加了这个变量,C程序在读取什么时会遇到一些问题我正在通过,我不明白什么是错的。
任何建议?



(考虑到在实际情况下,我将传递多个变量以及2个输入和2个输出数组(4维) 。



非常感谢您提前付款!!

解决方案

更改界面到:


$ b $ pre $ 模块raytracing
接口
整数(C_INT)函数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
结束函数photon_trace
结束接口
结束模块raytracing

你的C函数需要一个 double 而不是 double * ,所以你需要用属性传递标量,以便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.000000000 0000000
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


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!!

解决方案

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  

这篇关于ISO_C_BINDING从Fortran调用C例程(使用双精度和数组)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆