我调用了一个Fortran函数,其第一个参数是一个函数,我想使用该函数的C ++成员函数,
void Obj::memberF(double* x,double* res)
Obj
禁用了复制构造函数(这一点很重要,如下所示)。
Fortran子程序的格式为
subroutine solve(f,len,x)
f
有两个参数x
和rhs
,两者都是真正的数组。 len
代表这些数组的长度。
(基本上,需要在非线性求解器库中调用残差函数)
为此目的,无论最终的C ++方法如何,我们都需要一个活页夹,如下所示
binder.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 ++程序,首先,这些函数需要一个包装器
wrap.h
extern "C" {
void cpp_f(double*,double*);
void cpp_solve(void (Obj::*cpp_f)(double*,double*),int*,double*);
}
主程序如下
的main.cpp
#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
的复制构造函数由于其他原因而被禁用,并且是约束。这使我无法使用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例程,因此这是一些改造。
答案 0 :(得分:2)
如果这是一个单线程程序,一个实用的方法可以使用带有额外函数的全局指针变量
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)
...