Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

raw function pointer from a bound method

I need to bind a method into a function-callback, except this snippet is not legal as discussed in demote-boostfunction-to-a-plain-function-pointer.

What's the simplest way to get this behavior?

struct C {
void m(int x) {
    (void) x;
    _asm int 3;
}};

typedef void (*cb_t)(int);
int main() {
    C c;
    boost::function<void (int x)> cb = boost::bind(&C::m, &c, _1);
    cb_t raw_cb = *cb.target<cb_t>(); //null dereference
    raw_cb(1);
    return 0;
}
like image 747
Dustin Getz Avatar asked Oct 25 '25 06:10

Dustin Getz


1 Answers

You can make your own class to do the same thing as the boost bind function. All the class has to do is accept the function type and a pointer to the object that contains the function. For example, this is a void return and void param delegate:

template<typename owner>
class VoidDelegate : public IDelegate
{
public:
   VoidDelegate(void (owner::*aFunc)(void), owner* aOwner)
   {
      mFunction = aFunc;
      mOwner = aOwner;
   }
   ~VoidDelegate(void)
   {}
   void Invoke(void)
   {
      if(mFunction != 0)
      {
         (mOwner->*mFunction)();
      }
   }

private:
   void (owner::*mFunction)(void);
   owner* mOwner;
};

Usage:

class C
{
   void CallMe(void)
   {
      std::cout << "called";
   }
};
int main(int aArgc, char** aArgv)
{
   C c;
   VoidDelegate<C> delegate(&C::CallMe, &c);
   delegate.Invoke();
}

Now, since VoidDelegate<C> is a type, having a collection of these might not be practical, because what if the list was to contain functions of class B too? It couldn't.

This is where polymorphism comes into play. You can create an interface IDelegate, which has a function Invoke:

class IDelegate
{
   virtual ~IDelegate(void) { }
   virtual void Invoke(void) = 0;
}

If VoidDelegate<T> implements IDelegate you could have a collection of IDelegates and therefore have callbacks to methods in different class types.

like image 185
Chap Avatar answered Oct 26 '25 19:10

Chap