Reputation: 54143
I'm using a library that has callbacks like this:
void onReceive (Lacewing::Server &Server, Lacewing::Server::Client &Client,
char * Data, int Size) {
/* callback body */
}
Server.onReceive (onReceive); /* to register the handler */
I would like to be able to wrap this in a class that can decide what to do when it receives a packet (observer pattern).
How can I do this with C style callbacks? The library does not define an interface to inherit from.
Thanks
Upvotes: 6
Views: 423
Reputation: 16718
Since you're using liblacewing, every class has a void * Tag
member provided for user data:
/* class method */
void MyServer::onReceive (Lacewing::Server &Server, Lacewing::Server::Client &Client,
char * Data, int Size)
{
/* callback body - this is inside the class */
}
/* global function wraps the class method */
void onReceive (Lacewing::Server &Server, Lacewing::Server::Client &Client,
char * Data, int Size)
{
((MyServer *) Server.Tag)->onReceive (Server, Client, Data, Size);
}
then:
Server.Tag = myServerInstance; /* set the class instance pointer */
Server.onReceive (::onReceive); /* register the global function */
Upvotes: 2
Reputation: 317
If I understand you correctly, you could do it 2 different ways.
Assuming that this callback structure is using the Data parameter to allow you to pass your own data to the callback function (a common paradigm), you could do it like this:
class MyProcessingClass
{
public:
MyProcessingClass();
virtual ~MyProcessingClass();
// Do whatever processing in this method
virtual void onReceive(Lacewing::Server &Server, Lacewing::Server::Client &Client);
}
void onReceive (Lacewing::Server &Server, Lacewing::Server::Client &Client,
char * Data, int Size)
{
if ( Data != NULL )
{
MyProcessingClass *handler = reinterpret_cast<MyProcessingClass *>(Data);
handler->onReceive( Server, Client );
}
}
Or, if the data pointer is something you need to process instead of a "user data pointer", you'd probably have to use a singleton, some kind of global variable, or similar. In my experience, this is a less common way to use callbacks, and hopefully isn't what you're dealing with.
MyProcessingClass g_Processor;
MyProcessingClass *GetProcessor()
{
return &g_Processor; // or some other way of getting your instance
}
void onReceive (Lacewing::Server &Server, Lacewing::Server::Client &Client,
char * Data, int Size)
{
MyProcessingClass *handler = GetProcessor();
if ( handler != NULL )
{
handler->onReceive( Server, Client );
}
}
Upvotes: 1