views:

168

answers:

3

I have got a problem with calling a global function, which takes a pointer to a function as a parameter. Here is the declaration of 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(&LT_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?

+3  A: 

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.

Tom
+1  A: 

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, ...);
Mike Seymour
+4  A: 

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(&LT_Calibrator::fcn, &someCalibrator, m, n, x, fvec, ftol);
Jay Walker