简体   繁体   English

从C调用返回Fortran函数的数组

[英]Calling an array returning Fortran function from C

I have an already existing Fortran source code that I am working on adding C to, and am having difficulty with passing an array from C into a Fortran function and then receiving another array back. 我已经有一个要添加C的Fortran源代码,并且很难将数组从C传递到Fortran函数中,然后再接收另一个数组。

It compiles without any errors, but when I attempt to run the code, it says that: 编译时没有任何错误,但是当我尝试运行代码时,它说:

"Dimension of array 'p2' (In Fortran Function) has extent 3 instead of -4537421815 (or some other similar number)" “数组'p2'的维数(在Fortran函数中)具有范围3,而不是-4537421815(或其他类似的数字)”

I am not sure what is going on here. 我不确定这是怎么回事。 I will attach the two codes below. 我将在下面附加两个代码。

NOTE : I have removed a lot of the extra variable initialization lines which I think seems unnecessary for finding the problem. 注意 :我删除了很多多余的变量初始化行,我认为这对于发现问题似乎是不必要的。

C function: 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: 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

Fortran functions which return an array actually use a hidden argument and are implemented similarly to subroutines. 返回数组的Fortran函数实际上使用一个隐藏参数,并且与子例程的实现类似。 This is why you can't easily write a compatible C function, because you can't portably determine the hidden argument properties. 这就是为什么您不能轻松编写兼容的C函数的原因,因为您无法便携地确定隐藏的参数属性。

For example 例如

function f() result(res)
  real :: res(3)
  res = [1.,2.,3.]
end

looks in the GCC internal code as 在GCC内部代码中看起来是

f (struct array1_real(kind=4) & __result)
{
}

I suggest to convert the function to a subroutine. 我建议将函数转换为子例程。 That way you can exactly control the argument (parameter) for the array and you can make a C interface: 这样,您可以精确控制数组的参数(参数),并可以创建C接口:

  subroutine project(p1,p2,mydt,myi,myj,myk) bind(C)
    real(WP), dimension(3), intent(out):: p2
    ...

or you can write a wrapper subroutine which calls your function to maintain the Fortran functionality unchanged. 或者,您可以编写包装程序子例程,该例程调用您的函数以保持Fortran功能不变。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM