So below is a basic idea of what I'm trying to do. I have an external library that I would like to use in an existing project. I cannot change anything in the external library or the main function in the existing project of course.
The problem I face is how to pass a callback function I make in my class to this external function as a pointer to function. At the same time, this callback function has to have access to members of the class so I cannot simply make it static. How can I do it?
Class ExternalClass //This I cannot mess with.
{
//somestuff
void ExternalFunc (void(* callback)(int, const void*), const void *);
}
Class MyClass
{
//somestuff
ExternalClass m_ExObj;
void Callback(int x, const void *p){
//dosomething
//How do I use this pointer ?
}
void MyFunc(){
m_ExObj.ExternalFunc(/*Some way to put MyClass::Callback() in here*/)
}
}
The callback you have shown does not allow a user-defined value to be passed to it (otherwise you could use that for passing around your object pointer). It expects a standalone non-class function, so you have two options:
1) if the callback only ever calls into a single object at one time, then you can store the object pointer in a global or
static
variable, and then use a standalone function (orstatic
class method) as the callback and have it use the global/static pointer to call your class method:2) if you need to have callbacks for multiple objects at a time, you will have to wrap your class method inside a per-object thunk, where each thunk knows which object to call into, and then you use the thunks as callbacks. This is a more advanced technique, requiring an understanding of x86/x64 assembly and calling conventions, as you have to allocate memory dynamically and populate it with assembly instructions for each thunk to execute at runtime. For example, at least on Windows 32bit:
When
ExternalFunc()
calls its callback, it will be calling the thunk, executing the instructions it contains. The thunk above is injecting the object'sthis
pointer into the call stack as a parameter forCallback()
as ifExternalFunc()
had called it directly.Update: in lieu of new information about the callback actually accepting a user-defined value, that greatly simplifies things: