Pointer to a C++ class member function as a global function's parameter?
I have got a problem with calling a global function, which takes a pointer to a function as a parameter. Here is the declaration o开发者_运维技巧f the global function:
int lmdif ( minpack_func_mn fcn, void *p, int m, int n, double *x,
double *fvec, double ftol)
The "minpack_func_mn" symbol is a typedef for a pointer to a function, defined as:
typedef int (*minpack_func_mn)(void *p, int m, int n, const double *x,
double *fvec, int iflag );
I want to call the "lmdif" function with a pointer to a function which is a member of a class I created, and here is the declaration of this class function:
int LT_Calibrator::fcn(void *p, int m, int n, const double *x,
double *fvec,int iflag)
I am calling a global function like this:
info=lmdif(<_Calibrator::fcn, 0, m, n, x, fvec, ftol)
Unfortunately, I get a compiler error, which says: "error C2664: 'lmdif' : cannot convert parameter 1 from 'int (__thiscall LT_Calibrator::* )(void *,int,int,const double *,double *,int)' to 'minpack_func_mn' 1> There is no context in which this conversion is possible"
Is there any way to solve that problem?
It looks to me like the lmdif function takes the "void *p" as a user argument that it just passes to the callback (minpack_func_mn fcn).
If that is the case, just make LT_Calibrator::fcn a static function, and pass your object as the "p" parameter. Then you can cast the user-argument (p) to get your object back, if you want.
class LT_Calibrator
{
public:
static int fcn(void *p, int m, int n, const double *x, double *fvec,int iflag)
{
LT_Calibrator* pCalibrator = static_cast<LT_Calibrator*>( p );
}
};
Then call like:
LT_Calibrator someCalibrator;
info=lmdif(<_Calibrator::fcn, &someCalibrator, m, n, x, fvec, ftol);
Essentially there is an implicit argument for a member function (the this
pointer) which makes this tricky. Check out this FAQ entry for more information.
You need a non-member or static member function; a member function pointer can't be used in place of your function type because it requires an instance to call it on.
If your function doesn't need access to a LT_Calibrator
instance, then you can simply declare it static, or make it free function. Otherwise, it looks like you can use the first argument (void *p
) to pass an instance pointer into a "trampoline" function, which can then call a member function. Something along the lines of this:
// member function
int LT_Calibrator::fcn(int m, ...);
// static (or non-member) trampoline
static int fcn_trampoline(void *p, int m, ...)
{
return static_cast<LT_Calibrator*>(p)->fcn(m,...);
}
info = lmdif(&fcn_trampoline, this, m, ...);
精彩评论