[英]Pass pointer-to-member-function for class without copy constructor into Fortran
我有一个 Fortran 函数的调用,它的第一个参数是一个函数,我想使用形式的 C++ 成员函数,
void Obj::memberF(double* x,double* res)
Obj
禁用了复制构造函数(这变得很重要,如下所示)。
Fortran 子程序的形式为
subroutine solve(f,len,x)
f
接受两个参数x
和rhs
,它们都是实数数组。 len
代表这些数组的长度。
(本质上,需要在非线性求解器库中调用残差函数)
为此,无论最终的 C++ 方法如何,我们都需要一个活页夹,如下所示
活页夹.f90
SUBROUTINE cpp_solve(cpp_f,len,x) BIND(C, NAME='cpp_solve')
USE, INTRINSIC :: iso_c_binding, ONLY : c_int, c_float
INTERFACE
SUBROUTINE cpp_f(x,rhs) BIND(C)
USE, INTRINSIC :: iso_c_binding, ONLY : c_float
REAL(c_float) :: x(:)
REAL(c_float) :: rhs(:)
END SUBROUTINE cpp_f
END INTERFACE
INTEGER(c_int) :: len
REAL(c_float) :: x(len)
CALL solve(cpp_f,len,x)
END SUBROUTINE cpp_solve
对于C++程序,首先这些函数需要一个包装器
包裹.h
extern "C" {
void cpp_f(double*,double*);
void cpp_solve(void (Obj::*cpp_f)(double*,double*),int*,double*);
}
主要程序如下
主程序
#include "wrap.h"
int main {
int len = 2;
std::vector<double> x(len);
// Multiple lines to initialize foo
// Creating a global Obj is not feasible
// ...
Obj current_object(foo);
// WHAT GOES HERE?
// cpp_solve(...,len,x);
}
下面是我考虑过的一些方法,从最近的 C++ 特性开始,
1)注意Obj
的copy-constructor由于其他原因被禁用,是约束。 这阻止我使用std::bind
附加当前实例并获取函数指针。
2)另外,定义另一个函数extra_function(Obj& obj, double*,...)
然后使用 lambda 来只返回obj.memberF
是一个选项,因为这需要我指定一个捕获,给定自定义对象我只需要一个函数指针。
3)更简单的选择是只获取成员函数指针,然后按如下方式传递当前实例
typedef void (Obj::*fptr)(double*,double*);
fptr current_fPointer = &Obj::memberF;
cpp_solve(current_object.*current_fPointer,len,x);
这给了我“非静态成员函数的无效使用”错误。
有没有我可以用来获取函数指针的替代方法?
TBH,我实际上是在尝试使用这些 C++11 功能调用 Fortran 77 例程,所以这是一些逆向未来主义。
如果这是一个单线程程序,实用的方法可以使用带有额外函数的全局指针变量
static Obj *g_obj;
static void extra_func(double *x1, double *x2)
{
g_obj->memberF(x1, x2);
}
void call_f77(Obj *o1, int *len, double *x)
{
g_obj = o1;
cpp_solve(extra_func, len, x);
}
另一种方法,如果您可以修改 Fortran 代码(并且 Fortran 可以以某种方式透明地传递对象指针),您可以通过 Fortran 将相关对象隧道传输到extra_func
,例如
static void extra_func(void *p, double *x1, double *x2)
{
Obj *obj = static_cast<Obj*>(p);
obj->memberF(x1, x2);
}
void call_f77(Obj *o1, int *len, double *x)
{
cpp_solve(extra_func, o1, len, x);
}
在 Fortran 中(请原谅,我从未见过任何 Fortran 代码):
SUBROUTINE solve(cpp_f, obj, len, x)
...
CALL cpp_f(obj, x, rhs)
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.