我在论坛上寻找解决方案,但我失败了。我的主要问题是我太过于使用C语言和Fortran-C互操作性,以便了解我做错了什么。
我想从Fortran调用一个C例程,但我对变量的声明有问题。我做了一个例子。
这是C例程:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
#undef I
int photon_trace(double x_init[4], double x_final[4])
//***************************************************
{
double r,m,t,phi;
t = x_init[0];
r = x_init[1];
m = x_init[2];
phi = x_init[3];
t=t+1.0;
r=r+1.0;
m=m+1.0;
phi=phi+1.0;
x_final[0] = t;
x_final[1] = r;
x_final[2] = m;
x_final[3] = phi;
return 0;
}
这是Fortran的主要程序:
program main_dummy
! compile: f95 raytracing.f90 main_dummy.f90 dummy_trace.o -o main
use, intrinsic :: ISO_C_BINDING
use raytracing
implicit none
real(C_FLOAT), dimension(0:3) :: x_in, x_fin
x_in = (/1,2,3,4/)
x_fin = (/0,0,0,0/)
write(*,*)'x_in, x_fin before = ', x_in, x_fin
call photon_trace(C_FLOAT(x_in),C_FLOAT(x_fin))
write(*,*)'x_in, x_fin after = ', x_in, x_fin
end program main_dummy
这是带有界面的模块:
module raytracing
Interface
integer (C_INT) function photon_trace(x_init, x_final) &
bind(C, name='photon_trace')
use , intrinsic :: ISO_C_BINDING
implicit none
type (c_ptr), value :: x_init, x_final
end function photon_trace
end interface
end module raytracing
根据在C中给我例程的那个人,x_init
和x_final
应该是指针(对吧?)。
当我尝试编译时,当我在主程序中调用photon_trace
时,它会在参数列表中出现错误。
有什么建议吗?我正在使用gcc 4.8
P.S。 gcc 4.4是否具有与iso_c_binding
相同的功能,还是我需要做一些不同的使用它?
VLADIMIR评论后编辑:
谢谢弗拉基米尔!我正在调用该函数,因为我在此示例https://stackoverflow.com/tags/fortran-iso-c-binding/info
上看到了它我做了你建议的修改,现在编译! 问题是C例程似乎与变量的地址有关,而不是变量本身。
我在C例程中放了一些打印:
int photon_trace(double x_init[4], double x_final[4])
//***************************************************
{
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;
}
以及主要:
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_FLOAT), dimension(0:3) :: x_in, x_fin
integer :: rt_ok
x_in = (/1,2,3,4/)
x_fin = (/0,0,0,0/)
write(*,*)'x_in, x_fin before = ', x_in, x_fin
rt_ok = photon_trace(x_in,x_fin)
write(*,*)'return rt = ', rt_ok
write(*,*)'x_in, x_fin after = ', x_in, x_fin
end program main_dummy
这就是屏幕上的内容:
x_in, x_fin before = 1.00000000 2.00000000 3.00000000 4.00000000 0.00000000 0.00000000 0.00000000 0.00000000
t0 2.000000
r0 512.000123
m0 2.000000
phi0 512.000123
t1 3.000000
r1 513.000123
m1 3.000000
phi1 513.000123
return rt = 0
x_in, x_fin after = 1.00000000 2.00000000 3.00000000 4.00000000 1.00000000 2.12500000 3.00000000 4.00097656
这里发生了什么?
非常感谢您的宝贵帮助!!
答案 0 :(得分:4)
不要过度复杂化。不要传递指针,但是通过引用传递数组
此外,必须在表达式中使用函数,而不是在调用语句中使用。
module raytracing
Interface
integer (C_INT) function photon_trace(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)
end function photon_trace
end interface
end module raytracing
program main_dummy
! compile: f95 raytracing.f90 main_dummy.f90 dummy_trace.o -o main
use, intrinsic :: ISO_C_BINDING
use raytracing
implicit none
real(c_double), dimension(0:3) :: x_in, x_fin
integer ie
x_in = (/1,2,3,4/)
x_fin = (/0,0,0,0/)
write(*,*)'x_in, x_fin before = ', x_in, x_fin
ie = photon_trace(x_in,x_fin)
write(*,*)'x_in, x_fin after = ', x_in, x_fin
end program main_dummy
在C互操作过程中,Fortran会传递指向变量的指针,除非您使用value
。这称为按引用传递。
> gfortran ray.c ray.f90
> ./a.out
x_in, x_fin before = 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
x_in, x_fin after = 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000
P.S。 gcc 4.4很老了,但理论上它知道C interop的东西。试试吧,你会看到。