1

This question is based upon: Calling C++ class methods via a function pointer

What i would like to do is to register a generic object member function to a module lower in the architecture, that can invoke an event callback.

What i need is being able to register any object type (generic), so i do not have to have a registration function for each type of object.

Example from 1:

typedef void(Dog::*BarkFunction)(void);

Then to invoke the method, you use the ->* operator:

(pDog->*pBark)();

Example in my code:

// application layer
class ObjectInHighterLayer
{
    ObjectInHighterLayer()
    {
        xyz::registerEventhandler(this, eventCallback); // ??? how to register here ???
    }
    void eventCallback(int x)
    {

    }
}

// middleware layer or hal layer
static clientcallback clientCb = NULL;
namespace xyz {

  typedef void (GENERIC_OBJECT_TYPE::*clientcallback)(int /*x*/); // ??? how to define callback type here ???

  void registerEventhandler(clientcallback cb);
  {
      clientCb = cb;
  }

  void task()
  {
    // ... if event happend
    callClients();

  }

  void callClients()
  {
    if(clientCb != NULL)
    {
        clientCb(3);
    }
  }
}

1 Answers1

0

There are two patterns I am aware of...

virtual

All the callback functions share a class hierarchy, so a single virtual function can be used to dispatch to the correct type.

class CallbackBase {
     public:
          virtual void anEvent(int myEvent) = 0;
};

This can be registered by a class directly.

class ObjectInHighterLayer
{
    ObjectInHighterLayer()
    {
        xyz::registerEventhandler(this, eventCallback); // ??? how to register here ???
    }
    void anEvent(int myEvent)
    {
     // receive callback
    }
}

Or indirectly (probably better to use std::function)

class Test {
public:
    void callable(int ) {
    }
};
typedef void (Test::*Callable)(int);

This can then be called by a proxy object, separating the hierarchy of the callbacks from that of the called.

class MyFunction {
public:
    Callable m_f;
    Test * m_Test;
    MyFunction( Test * pTest, Callable fn) : m_Test(pTest), m_f( fn )
    {

    }
    void anEvent( int x ) {
        (m_Test->*m_f)(x);
    }
};

Allowing different functions of test to be registered for different callbacks.

static callback

Change the callback mechanism to take an opaque type.  This is easier to code, although sacrifices type-safety.

 class Callbackable {
     static void callback1( void * pThis, int param )
     {
         Callbackable *_this = static_cast<Callbackable*>( pThis );
         _this->callFunction( param );
     }
 }

The callback1 because it is static shares a function type with similar functions in different classes (outside of any hierarchy). The idea that it is called with an incorrect pThis is the type safety weakness.

mksteve
  • 12,614
  • 3
  • 28
  • 50