Reputation: 3079
Im writing a simple socket server in C++. I've already have some libs from C which fires callback when event read happens on socket. I want client who will use that class will impement its own mechanims to handle those events. My base class is:
class CBaseServer{
...
void monitorDataArrived(int fd);
virtual void monitorOnDataArrived(void *context, int fd) = 0;
}
in this class pointer to monitorOnDataArrived(void *context, int fd)
has to be passed to extarnal C function called AddClient(int mask, proc, fd)
whenever new socket will appear. proc
is defined as:
typedef void(*proc)(void *context, int fd)
CBaseServer::monitorDataArrived(fd){
proc p = (void (*)(void*, int)&CBase::monitorOnDataArrived;
addClient(MASK_READ, p, fd);
}
now client is doing:
class Reader : class CBase{
void monitorOnDataArrived(void *context, int fd) {
std::cout << "hey, data arrived"
}
}
My question is: im having compliation errors: undefined refernece to CBaseServer::monitorOnDataArrived(void *, int)
Is there any way to fix it ?
regards J.
Upvotes: 0
Views: 278
Reputation: 2595
You are misunderstanding the function pointers in C++.
You cannot pass a member function to a C handler, since a member function has an additional implicit parameter (the "this" parameter).
What is the solution? The solution is to use static functions which will cast the void * context parameter into an instance of your base class, and then calling the virtual function:
class CBaseServer{
...
//Watch that the context parameter has been moved from the virtual to the other
//function, which is now also static.
static void monitorDataArrived(void *context, int fd);
virtual void monitorOnDataArrived(int fd) = 0;
}
The dispatching code would be as following:
void CBaseServer::monitorDataArrived(void *context, int fd){
CBaseServer * server=(CBaseServer*)context;
server->monitorOnDataArrived(fd);
}
And the registration code would be:
class Reader : class CBase{
void monitorOnDataArrived(int fd) {
std::cout << "hey, data arrived"
}
}
....
Reader * theReader=new Reader();
//The instance theReader of type Reader must be passed to the registration function
//as the void * context parameter.
addClient(MASK_READ, &theReader);
Upvotes: 3