绑定 C++ 和 Fortran

Binding C++ and Fortran

我想将 C++ 和 Fortran 结合在一起。我的 Fortran 代码将使用 C++ 函数,C++ 函数更改 Fortran 的变量并将它们发回。 C++ 函数是用其他 C++ 代码构建的,例如C++ 函数将使用其他 .cpp 文件中的一些子函数。我用 ifort 制作 Fortran 代码,并在我的 Fortran 生成文件中添加了 C++ 函数作为一个目标文件 test.o。我还将所有需要的 C++ .o 文件(支持 test.o)放入 makefile 中。它显示错误

#6633, "The type of the actual argument differs from the type of the dummy argument".

这是代码。

Fortran 代码

  use, intrinsic :: ISO_C_BINDING, only: C_INT, C_DOUBLE   
  implicit double precision(a-h,o-z),integer(i-n)
  Interface
   integer (C_INT) function SolveBIE_(x, y, aa, m) BIND(C, NAME='SolveBIE_')
   use, intrinsic :: ISO_C_BINDING
   implicit none
   type (C_PTR), value :: x
   type (C_PTR), value :: y
   type (C_PTR), value :: aa
   integer (C_INT), value :: m
   end function SolveBIE_
  end Interface
  integer (C_INT) :: m
  real (C_DOUBLE), ALLOCATABLE, DIMENSION(:,:), target :: x
  real (C_DOUBLE), ALLOCATABLE, DIMENSION(:,:), target :: y
  real (C_DOUBLE), ALLOCATABLE, DIMENSION(:,:), target :: aa
  ALLOCATE(x(0:MAXLEN,MAXINTERFACES))
  ALLOCATE(y(0:MAXLEN,MAXINTERFACES))
  ALLOCATE(aa(0:MAXLEN,MAXINTERFACES))

我的 Fortran 代码运行

  mm = SolveBIE_(x(1,1),y(1,1),aa(1,1),m) 

x, y, aa 上使用 C++ 代码和错误来源 我使用 x(1,1) 而不是 x,因为如果使用 x,则会出现另一个错误

#6634,"the shape matching rules of actual arguments and dummy arguments have been violated"`

我不明白为什么应该是 x(1,1)。为什么这是有效的,而不是 x?

我的 C++ 代码

  #ifdef __cplusplus
  extern "C" {
  #endif
  int solveBIE_(double *ini_bdry_x, double *ini_bdry_y, double *ini_bdry_um, int *fM)
{  
     double(*bdry_node)[2] = new double[M1][2];
     for (int k = 0; k < M; k++) {
        bdry_node[k+1][0] = ini_bdry_x[k+1];
        bdry_node[k+1][1] = ini_bdry_y[k+1];
        bdry_theta[k+1] = Atan(ini_bdry_x[k+1], ini_bdry_y[k+1]);}

    ... some functions in other .cpp file

按照你的界面编写方式,你必须构造一个 C_PTR 到数组 x 并将其作为第一个参数传递:

use, intrinsic :: ISO_C_BINDING, only: C_INT, C_DOUBLE, C_PTR, C_LOC
! ...
type(C_PTR) PTRx
! ...
PTRx = C_LOC(x(LBOUND(x,1),LBOUND(x,2)))
! ...
mm = solveBIE_(PTRx, PTRy, PTRaa, m)

如上所示,您还必须修正接下来的两个参数。但是您需要重写参数 fM 的接口,因为就目前而言,Fortran 将按值传递整数,而 C++ 需要指针。鉴于此,我将完全重写接口,使用为 C++ 函数中的参数指定的名称并通过引用传递所有内容。伪参数的名称在 Fortran 中可能是可见的,因此让它们有意义是很有用的。在下文中,我假设 fM 指向被调用方中的一个标量:

  Interface
   function SolveBIE_(ini_bdry_x, ini_bdry_y, ini_bdry_um, fM) &
      BIND(C, NAME='SolveBIE_')
   import
   implicit none
   integer(C_INT) SolveBIE_
   real(C_DOUBLE) :: ini_bdry_x(*)
   real(C_DOUBLE) :: ini_bdry_y(*)
   real(C_DOUBLE) :: ini_bdry_um(*)
   integer (C_INT) :: fM
   end function SolveBIE_
  end Interface

之后您可以或多或少地正常调用它,如

mm = SolveBIE_(x,y,aa,m)

请注意,x(1,1) 是错误的,因为 LBOUND(x,1) = 0,而不是 1