我有一个已经存在的Fortran源代码我正在努力添加C,并且很难将数组从C传递到Fortran函数然后再接收另一个数组。
它编译没有任何错误,但当我尝试运行代码时,它说:
“数组'p2'的维度(在Fortran函数中)具有范围3而不是-4537421815(或其他一些类似的数字)”
我不确定这里发生了什么。我将附上以下两个代码。
注意:我已经删除了很多额外的变量初始化行,我认为这些行似乎没有必要找到问题。
C函数:
#include <stdio.h>
#include <stdlib.h>
extern "C" double* __multiphase_tools_MOD_project(double p1[],double *mydt,int *myi,int *myj,int *myk);
extern "C" void cuda_(int *ptr_band, double *ptr_u, double *ptr_v, double *ptr_w)
{
double *pt_out;
double pt_in[3];
// Loop over the domain and compute fluxes near interfaces
//=======================================================================================
// X FACE
//=======================================================================================
for (k = kmin; k <= kmax; k++)
{
for (j = jmin; j <= jmax; j++)
{
for (i = imin; i <= imax; i++)
{
if (abs(band[i-1][j][k]) <= nband_CFL && abs(band[i][j][k]) <= nband_CFL )
{
for (int n = 1; n < 10; n++)
{
pt_in[0] = pt[0][n][1]; pt_in[1] = pt[1][n][1]; pt_in[2] = pt[2][n][1];
pt_out = __multiphase_tools_MOD_project(pt_in,&neg_dt_uvw,&i,&j,&k);
}
}
}
}
}
return;
}
Fortran功能:
function project(p1,mydt,myi,myj,myk) result(p2)
use math
use iso_c_binding
implicit none
real(WP), dimension(3) :: p2
real(WP), dimension(3), intent(in) :: p1
real(WP), intent(in) :: mydt
integer, intent(in) :: myi,myj,myk
real(WP), dimension(3) :: v1,v2,v3,v4
v1=get_velocity(p1 ,myi,myj,myk)
v2=get_velocity(p1+0.5_WP*mydt*v1,myi,myj,myk)
v3=get_velocity(p1+0.5_WP*mydt*v2,myi,myj,myk)
v4=get_velocity(p1+ mydt*v3,myi,myj,myk)
p2=p1+mydt/6.0_WP*(v1+2.0_WP*v2+2.0_WP*v3+v4)
return
end function project
答案 0 :(得分:3)
返回数组的Fortran函数实际上使用隐藏参数,并且与子例程类似地实现。这就是为什么你不能轻易编写兼容的C函数,因为你无法轻松地确定隐藏的参数属性。
例如
function f() result(res)
real :: res(3)
res = [1.,2.,3.]
end
在GCC内部代码中查找为
f (struct array1_real(kind=4) & __result)
{
}
我建议将该函数转换为子例程。这样你就可以精确地控制数组的参数(参数),你可以创建一个C接口:
subroutine project(p1,p2,mydt,myi,myj,myk) bind(C)
real(WP), dimension(3), intent(out):: p2
...
或者您可以编写一个包装器子例程来调用您的函数以保持Fortran功能不变。