绑定C ++和Fortran [英] Binding C++ and Fortran
问题描述
我想将C ++和Fortran结合在一起。我的Fortran代码将使用C ++函数,而C ++函数会更改Fortran的变量并将其发回。 C ++函数是用其他C ++代码构建的,例如, C ++函数将在其他.cpp文件中使用一些子函数。我使用 ifort
创建Fortran代码,并将C ++函数作为一个目标文件添加到我的Fortran生成文件中的test.o中。我还将每个需要的C ++ .o文件(支持test.o)放在makefile中。它显示错误
#6633,实际参数的类型与伪参数的类型不同。
以下是代码。
Fortran代码
use,intrinsic :: ISO_C_BINDING,only:C_INT,C_DOUBLE
隐式双精度(ah,oz),整数(in)
接口
整数(C_INT)函数SolveBIE_(x,y,aa,m)BIND(C,NAME ='SolveBIE_')
内部使用:: ISO_C_BINDING
隐式无
type(C_PTR),value :: x
type(C_PTR),value :: y
type(C_PTR),value :: aa
integer(C_INT),value :: m
结束函数SolveBIE_
结束接口
整数(C_INT):: m
实数(C_DOUBLE),ALLOCATABLE,DIMENSION(:, :),target :: x
(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)
使用C ++代码以及错误来自 我不明白为什么它应该是 我的C ++代码 您的界面写入的方式,您必须构建一个 如图所示上面,你将不得不修复接下来的两个参数。但是你需要重写参数 然后,您可以正常或多或少地调用它作为 注意 I want to combine C++ and Fortran together. My Fortran code will use a C++ function and C++ function changes variables of Fortran and sends them back. The C++ function is built with other C++ codes, e.g. the C++ function will use some sub-function in other .cpp file. I make the Fortran code with #6633, "The type of the actual argument differs from the type of the dummy argument". Here is the code. Fortran code My Fortran code run Using the C++ code and where the error is from, on #6634,"the shape matching rules of actual arguments and dummy arguments have been violated"` I don't understand why it should be My C++ code
The way your interface is written, you have to construct a As shown above, you would have to fix the next two arguments as well. But you need to rewrite the interface for argument Then later on you can invoke it more or less normally as Note that 这篇关于绑定C ++和Fortran的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
我使用 x(1,1)
而不是 x
,因为如果使用 x
,那么还有另一个错误
$ block
6634,实际参数的形状匹配规则并且伪参数被违反了。``b $ b x(1, 1)
。为什么这是可行的,而不是 x
?
#ifdef __cplusplus
externC{
#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]; (int k = 0; k< M; k ++){
bryry_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]);}
...其他.cpp文件中的一些函数
C_PTR
到数组 x
并将其作为第一个参数传递:
use,intrinsic :: ISO_C_BINDING,只有:C_INT,C_DOUBLE,C_PTR,C_LOC
! ...
类型(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
指向被调用者的标量:
接口
函数SolveBIE_(ini_bdry_x,ini_bdry_y,ini_bdry_um,fM)&
BIND(C,NAME ='SolveBIE_')
导入
隐式无
整型(C_INT)SolveBIE_
真(C_DOUBLE):: ini_bdry_x(*)
real(C_DOUBLE):: ini_bdry_y(*)
real(C_DOUBLE):: ini_bdry_um(*)
整数(C_INT):: fM
结束函数SolveBIE_
结束接口
mm = SolveBIE_(x,y,aa,m)
x(1,1)
是错误的,因为 LBOUND(x,1)= 0
,而不是 1
!ifort
and I added that C++ function as one object file, test.o in my Fortran makefile. I also put every needed C++ .o file(support test.o) in makefile. It shows the error
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))
mm = SolveBIE_(x(1,1),y(1,1),aa(1,1),m)
x, y, aa
I use x(1,1)
instead of x
, because if using x
, then there is another error
x(1,1)
. Why is this working, not x
? #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
to array x
and pass that as the first argument: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
because as matters stand, Fortran will pass an integer by value whereas C++ is expecting a pointer. Given that, I would rewrite the interface completely, using the names given for the arguments in the C++ function and passing everything by reference. Names for dummy arguments are potentially visible in Fortran, so it's useful for them to be meaningful. In the following I assume that fM
points to a scalar in the callee: 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)
was wrong because LBOUND(x,1) = 0
, not 1
!