我正在考虑使用http://users.ics.forth.gr/~lourakis/levmar/中的库,该库是用C语言编写的。
但是我将它包含在成员函数“dlevmar_der”中,它希望有两个函数指针作为其参数:
int dlevmar_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, /* I/O: initial parameter estimates. On output contains the estimated solution */
double *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
int itmax, /* I: maximum number of iterations */
double opts[4],
double info[LM_INFO_SZ],
double *work,
double *covar,
void *adata
)
我有以下简化模板类,其中包含两个非静态成员函数CallBack和MyJac。 (假设我在类中也有m_solution,m_info等所有其他属性):
Template<class F>
class MyClass
{
public:
typedef void (MyClass<F>::*FuncPtrType)(float*);
void Start()
{
this->Run(&MyClass<F>::MyJac);
}
protected:
void Callback(ValueType x[], ValueType result[], int m, int n, void* adata){ // some code }
void MyJac(ValueType x[], ValueType result[], int m, int n, void* adata){ // some code }
void Run(FuncPtrType func)
{
int iterCount = dlevmar_der(&MyClass<F>::Callback, func,
(double*)&this->m_solution[0],
(double*)&zero[0],
this->m_function.NumberOfParameters,
this->m_function.NumberOfFunctionValues,
this->m_maxIterations,
this->m_options,
this->m_info,
NULL,
NULL,
static_cast<void*>(this));
}
}
但是,在调用Start()
函数时,我在“运行”函数中收到错误,说:error C2664: 'slevmar_der' : cannot convert from 'void (__thiscall MyClass<F>::* )(float *,float *,int,int,void *)' to 'void (__cdecl *)(float *,float *,int,int,void *)
我的问题是dlevmar_der
函数是否只能将函数指针指向静态成员函数?或者有什么方法可以使用dlevmar_der
实现非静态成员函数吗?
答案 0 :(得分:5)
你需要建立一个蹦床功能。
只需将this
作为adata
参数传递,然后编写一个回调函数,将adata
强制转换为正确的类型指针并调用该方法。例如:
void myFunc(double *p, double *hx, int m, int n, void *adata) {
MyClass *self = static_cast<MyClass>(adata);
self->funcMethod(p, hx, m, n, self->func_adata);
}
答案 1 :(得分:1)
编写静态包装器
template<class F>
class MyClass
{
protected:
void Callback(ValueType x[], ValueType result[], int m, int n) {
}
static void CallbackWrapper(
ValueType x[], ValueType result[], int m, int n,
void* adata)
{
static_cast<MyClass<T>*>(adata)->Callback(x, result, m, n);
}
void Run(FuncPtrType func)
{
int iterCount = dlevmar_der(
&MyClass<F>::CallbackWrapper, /*..*/ );
}
};
答案 2 :(得分:0)
C ++成员函数指针不能与常规函数指针互换使用。
但是,您通常可以安全地使用静态成员函数指针,其中需要C函数指针。您的C API看起来允许您将自己的void*
上下文参数传递给回调。您可以使用它将实例指针传递回静态方法,并使用它来调用您的isntance方法,如下所示:
static void StaticCallback(/* Args... */, void *user_data)
{
MyClass *ptr = static_cast<MyClass*>(user_data);
ptr->NonStaticCallback(/*args...*/);
}
(严格来说,你需要使用一个声明为extern "C"
的免费(非成员)函数来进行转发,但静态方法通常很好。)