绑定 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
!
我想将 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
!