ISO_C_BINDING 从 Fortran 调用 C 例程(使用双精度和数组) [英] ISO_C_BINDING Calling C routine from Fortran (with doubles and arrays)
问题描述
几周前我发布了一个类似的问题(iso_c_binding 使用来自 Fortran 数组的指针调用 C 例程),我找到了解决问题的方法.现在我修改了一些东西,我又遇到了一些问题.下面是我的问题的简化版本.
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.
我在 fortran 中有一个主程序:
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
其中使用包含 C 例程接口的子例程:
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
这是 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
", 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;
return 0;
}
如果我编译并运行程序,这就是我得到的:
If I compile and run the program, this is what I get:
x_in,x_fin = 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
x_in, x_fin before = 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
BHsp 0.000000
BHsp 0.000000
t0 0.700000
t0 0.700000
r0 0.000000
r0 0.000000
m0 0.700000
m0 0.700000
phi0 0.000000
phi0 0.000000
t1 1.700000
t1 1.700000
r1 1.000000
r1 1.000000
m1 1.700000
m1 1.700000
phi1 1.000000
phi1 1.000000
返回 rt = 0
x_in,x_fin = 1.6999999880790710 1.0000000000000000 1.0000000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
x_in, x_fin after = 1.6999999880790710 1.0000000000000000 1.0000000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
请注意,在放置变量spin"之前,一切正常.它可以读取输入数组,进行运算,并给出正确的输出.
Notice that before putting the variable "spin" everything was working. It could read the input array, make the opration, and give the right output.
现在我添加了 ths 变量,C 例程在读取我传递的内容时出现了一些问题,我无法理解出了什么问题.有什么建议吗?
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 ?
(考虑到在实际情况下,我将传递几个变量以及 2 个输入和 2 个维度为 4 的输出数组).
(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).
提前非常感谢!!
推荐答案
将界面更改为:
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 知道按值传递,而不是默认的按引用传递.
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.
通过这个小改动(以及对 C 的一些小改动以实际打印 m
和 phi
的值),这是示例代码的输出:
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屋!