Callback to member function using libevent - c++

I am trying to pass a member function to libevent which should be treated as a callback.
#include <event.h>
class A
{
public:
void eventcb(evutil_socket_t fd, short events, void *ctx) { }
};
static void global_eventcb(evutil_socket_t fd, short events, void *ctx) { }
typedef void (A::*mthd)(evutil_socket_t, short, void*);
int main(void)
{
struct event_base *evbase = event_base_new();
mthd eventcb = &A::eventcb;
A *instance = new A;
(instance->*eventcb)(NULL, 0, NULL);
struct event *timer1 = evtimer_new(evbase, global_eventcb, NULL);
struct event *timer2 = evtimer_new(evbase, (instance->*eventcb), NULL);
return 0;
}
I can successfully create a method pointer to eventcb in class A and call it on an instance of A (row 20).
Also, passing a global function (as one would do in C) on row 22 also works fine.
However, on row 23, I attempt to pass my method pointer to libevent, and when I compile this I get the following error (using the clang compiler)
example.cpp:23:25: error: no matching function for call to 'event_new'
struct event *timer2 = evtimer_new(evbase, (instance->*eventcb), NULL);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from example.cpp:1:
In file included from /usr/local/include/event.h:71:
/usr/local/include/event2/event.h:749:40: note: instantiated from:
#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
^~~~~~~~~
/usr/local/include/event2/event.h:833:15: note: candidate function not viable: no know conversion from '<bound member function type>' to 'event_callback_fn'
(aka 'void (*)(int, short, void *)') for 4th argument
struct event *event_new(struct event_base *, evutil_socket_t, short, event_callback_fn, void *);
^
1 error generated.
What am I doing wrong?

Instance method pointers need an instance to be invoked on. Since libevent is a C library, it doesn't directly provide a mechanism to associate an instance and an instance method, so you'll have to do it yourself. libevent's various event creation functions let you pass arbitrary data as a callback argument. The instance pointer can be passed via this argument, either directly or packaged in a class with other arguments if the callback takes additional data. The event callback can be a free function or a static method; which approach to take depends on the class's responsibility (in the SOLID, single-responsibilty sense).
An example using a static method and passing no additional data:
class A {
public:
A(struct event_base *);
bool start_timer();
static void invoke_timer_handler(evutil_socket_t fd, short events, void *ctx);
void handle_timeout(evutil_socket_t fd, short events);
protected:
struct event_base *evbase;
struct event *timer;
};
A::A(struct event_base *event_base) : evbase(event_base), timer(NULL) {}
bool A::start_timer() {
// not thread safe.
if (! timer) {
timer = evtimer_new(evbase, &A::invoke_timer_handler, this);
return true;
}
return false;
}
void A::invoke_timer_handler(evutil_socket_t fd, short events, void *ctx) {
(static_cast<A*>(ctx))->handle_timeout(fd, events);
}
void A::handle_timeout(evutil_socket_t fd, short events) {
...
if (evtimer_del(timer)) {
// error deleting event
...
} else {
timer=NULL;
}
}
In the example, since A::handle_timeout is only called from within A::invoke_timer_handler, it could be made private or protected.
The sample has very basic memory management. In general, the code must ensure the instance (and other callback arguments, if the callback argument isn't simply an A*) exists for the lifetime of the event to prevent access errors. It should also ensure the instance doesn't leak once the event is no longer needed. If the instance owns the event, memory management is relatively straightforward. Concurrency can also add complication that affect memory management.
Existing code-level implementations of anonymous functions (e.g. boost::lambda) and the forthcoming lambda expressions from C++11 rely on the function call operator (operator()), which is unsupported in plain C. Thus anonymous functions are unsuitable for use as libevent callbacks or any other C-library callbacks.

Related

Having an object merge two functions and passing them as a callback? (C++)

I'd like to have my class take a function "the callback stub", add some stuff that processes before and after the stub, and then pass the whole thing as a callback to an interrupt. Different stubs could be attached to different instances of the class.
I'm getting errors as shown in the comments below. It works to take a function pointer, store it as an attribute, and then pass it to the attachInterrupt function. However, it doesn't work to add the little prelude.
In setInterrupt(), I get a pointer to a bound function may only be used to call the functionC/C++(300)
altSetInterrupt() however compiles fine.
Question: Is there a combination of * & or -> that can make this work?
EDITED: to remove a silly mistake as pointed out by Jerry Jeremiah
#include <Arduino.h>
#define MYPIN 1
// Declarations
class myClass {
public:
myClass();
void setInterrupt();
void altSetInterrupt();
void setCallBackStub( void (*cb)());
private:
void (*myCallBackStub)();
void myCallBack();
};
void mySillyCB();
// Definitions
myClass::myClass():
myCallBackStub(nullptr)
{}
void myClass::setCallBackStub( void (*cb)()) {
myCallBackStub = cb;
}
void myClass::myCallBack() {
Serial.println("Wohoo");
myCallBackStub();
}
void myClass::setInterrupt() {
attachInterrupt(MYPIN, this->myCallBack, HIGH); // a pointer to a bound function may only be used to call the functionC/C++(300)
}
void myClass::altSetInterrupt() {
attachInterrupt(MYPIN, this->myCallBackStub, HIGH); // no compiler error here
}
void mySillyCB() {
Serial.println("Called Back");
}
// Code
myClass theThing;
void setup() {
theThing.setCallBackStub( mySillyCB);
theThing.setInterrupt();
}
void loop() {}
In myCallBack(), I get identifier "myCallBackStub" is undefinedC/C++(20)
You have defined this as a free function rather than implementing a method. You have:
void myCallBack() {
But you should have:
void myClass::myCallBack() {
Because of this, there is no such name myCallBackStub in scope.
In setInterrupt(), I get a pointer to a bound function may only be used to call the functionC/C++(300)
this->myCallBack is not a first-class value in C++; it is a member function that is bound to a particular instance (*this). The only thing you can do with this is invoke it (like this->myCallBack()).
Notably, you cannot convert it to a function pointer. This is because non-static member functions need an instance on which to invoke the function, and a free function pointer (what attachInterrupt accepts) has no additional mechanism to convey this state. Even if you used the correct syntax for a pointer-to-member-function (&myClass::myCallBack) this still would not work since you cannot convert between pointer-to-function and pointer-to-member-function.
You can pass this->myCallBackStub because this is actually a function pointer value.
Since attachInterrupt() state is global anyway, you don't gain a whole lot by not making your mechanism global. The primary challenge you are running into is that the callback function accepts no arguments so you can't even tell which pin/mode was used.
To get around this, you need a different non-member callback function per pin/mode combination, and these must be known in advance at compile time, since you (presumably) don't want to get into the complexity of emitting trampolines at runtime.
This can be done at compile time with the use of macros. Each invocation of the macro should do several things:
Declare a global callback function.
Declare a global vector of callback function objects that will be invoked by the global callback function.
Possibly invoke attachInterrupt() depending on whether this can be done during static initialization.
Here is a sample implementation of this concept, which may need tweaking to be useful in production. You would create a header like interrupts.hpp with the following:
#include <functional>
#include <vector>
// These types may need adjusting to match Arduino's types.
using Pin_t = int;
using Mode_t = int;
using InterruptCallback_t = std::function<void()>;
using InterruptCallbackList_t = std::vector<InterruptCallback_t>;
using RawInterruptCallback_t = void (*)();
#define DECLARE_INTERRUPT(pin, mode) DECLARE_INTERRUPT_(pin, mode)
#define DECLARE_INTERRUPT_(pin, mode) \
void add_interrupt_callback_##pin##_##mode (InterruptCallback_t);
DECLARE_INTERRUPT(0, 0)
// And so on...
Then in the implementation file interrupts.cpp:
#include <utility>
#include "interrupts.hpp"
static void apply_interrupt_callback(InterruptCallbackList_t const & cbList) {
for (const auto & cb : cbList) {
cb();
}
}
#define IMPLEMENT_INTERRUPT(pin, mode) IMPLEMENT_INTERRUPT_(pin, mode)
#define IMPLEMENT_INTERRUPT_(pin, mode) \
static InterruptCallbackList_t generated_interrupt_callbacks_##pin##_##mode ; \
static void generated_interrupt_callback_##pin##_##mode() { \
apply_interrupt_callback( generated_interrupt_callbacks_##pin##_##mode ); \
} \
void add_interrupt_callback_##pin##_##mode (InterruptCallback_t cb) { \
( generated_interrupt_callbacks_##pin##_##mode ).emplace_back(std::move(cb)); \
} \
static int generated_interrupt_registration_##pin##_##mode = ( \
attachInterrupt(pin, generated_interrupt_callback_##pin##_##mode, mode), \
0 \
);
IMPLEMENT_INTERRUPT(0, 0)
// And so on...
This will generate a set of functions and global variables for each pin/mode combination you provide. The interface provided by interrupts.hpp will expose add_interrupt_callback_N_M where N and M are the pin and mode constants, respectively. You can pass any function or functor (with the help of std::function<void()> to this function and it will be called when the interrupt occurs.
Note that there is no mutex in this example code. For the sake of simplicity, I assume a single-threaded environment, where an interrupt callback cannot occur preemptively. The code will need to be changed if these assumptions are not true.

Cast error passing a void function with namespace

I'm trying to wrap, in a C++ class, a server that I wrote using mongoose (a C library). The problem is that I'm trying to pass the function ev_handler to the mg_create_server(), which create the instance of the server in mongoose. But it gives a casting error I believe:
src/Server.cpp:16:44: error: cannot convert 'Server::ev_handler' from
type 'int (Server::)(mg_connection*, mg_event)' to type 'mg_handler_t
{aka int (*)(mg_connection*, mg_event)}' server =
mg_create_server(NULL, ev_handler);
I tried to make ev_handler static but it has send_index_page(conn) that has to be inside the wrapper class.
void Server::start() {
struct mg_server *server;
int numberOfObjects;
_application = new Application();
_application->start();
// Create and configure the server
server = mg_create_server(NULL, ev_handler);
//... more code here ...
}
int Server::ev_handler(struct mg_connection *conn, enum mg_event ev) {
switch (ev) {
case MG_AUTH: return MG_TRUE;
case MG_REQUEST: return send_index_page(conn);
default: return MG_FALSE;
}
}
Your problem is that you're passing a C++ member function to parameter that wants a free function pointer.
Mongoose is a C API and all of its callback parameters are C style functions, which in C++ are free (not member) functions.
A member function pointer is different from a free function pointer in that it needs the this , or the object on which the method is being called, in order to be called.
In your case, you are passing a member function pointer on the Server class.
When interacting which C APIs, it's common to pass a void* context object which is then passed to the callback. You then pass a pointer to a free function or a static class method (which has no this and can therefore work with C APIs). When the callback is invoked, you then cast the context object to the correct type and call a member function to get back into the object context. I can't see any such facility in Mongoose. Maybe it's there and I'm just not finding it.
You may want to try the already exising Mongoose C++ which forks the original Mongoose project to work better with C++: https://github.com/Gregwar/mongoose-cpp
The callback needs to be static, then you should use a static stub to redirect to the class instance.
Storing the instance of your class in server_param attribute of mg_server will allow to get it back in a static stub and forward it to this instance.
This could be achieve like this :
class Server
{
public:
void start() {
mg_create_server(this, ev_handlerStub);
}
static int ev_handlerStub(struct mg_connection *conn, enum mg_event ev) {
((Server*)conn->server_param)->ev_handler(conn, ev);
}
int ev_handler(struct mg_connection *conn, enum mg_event ev) {
// job to do with the class instance
}
};
Proceeding like this, allow access to class instance inside its ev_handler method.

non-member function pointer as a callback in API to member function

I'm using an API that requires me to pass a function pointer as a callback. I'm trying to use this API from my class in C++ but I'm getting compilation errors.
The API definition is:
typedef void (__stdcall *STREAM_CALLBACK)(void *userdata);
__declspec(dllimport) int __stdcall set_stream_callback(
STREAM_CALLBACK streamCB, void *userdata);
One example file, provided by the third party, is:
void __stdcall streamCB(void *userdata)
{
// callback implementation
}
int main(int argc, const char argv[])
{
int mid = 0;
set_stream_callback(streamCB, &mid);
}
And that works fine.
However when I try to use that in a class, I have an error:
error C3867: 'MyClass::streamCB': function call missing argument list;
use '&MyClass::streamCB' to create a pointer to member
The suggestion to use
&MyClass::streamCB
doesn't work.
I understood that the set_stream_callback only accepts a non-member function.
The problem is very similar to
How can I pass a class member function as a callback?
in which Johannes makes a concise suggestion, however I do not understand it very well. Could anyone expand a bit, if I am correct that it is relevant to this question?
I have tried:
void __stdcall MyClass::streamCB(void *userdata)
{
// callback implementation
}
static void MyClass::Callback( void * other_arg, void * this_pointer ) {
MyClass * self = static_cast<ri::IsiDevice*>(this_pointer);
self->streamCB( other_arg );
}
//and in the constructor
int mid = 0;
set_stream_callback(&MyClass::Callback, &mid);
But
error C2664: 'set_stream_callback' : cannot convert parameter 1 from
'void (__cdecl *)(void *,void *)' to 'STREAM_CALLBACK'
How do I get around this?
Edit1: Also, I want to use userdata inside the streamCB callback.
The idea of calling a member function from a callback taking only non-member functions is to create a wrapper for you member function. The wrapper obtains an object from somewhere and then calls the member function. If the callback is reasonably well designed it will allow you to pass in some "user data" which you'd use to identify your object. You, unfortunately, left out any details about your class so I'm assuming it looks something like this:
class MyClass {
public:
void streamCB() {
// whatever
}
// other members, constructors, private data, etc.
};
With this, you can set up your callback like so:
void streamCBWrapper(void* userData) {
static_cast<MyClass*>(userData)->streamCB()
}
int main() {
MyClass object;
set_stream_callback(&streamCBWrapper, &object);
// ...
}
There are various games you can play with how to create the streamCBWrapper function (e.g., you can make it a static member of your class) but all come down to the same: you need to restore your object from the user data and call the member function on this object.
You can achieve what you want to do by turning the userdata into a property of MyClass. Then you don't have to pass it to MyClass::Callback, which would be impossible, since you can only pass one parameter, and it would be the object instance.
Here's an example.
void __stdcall MyClass::streamCB()
{
// callback implementation
}
static void MyClass::Callback(void * this_pointer ) {
MyClass * self = static_cast<MyClass>(this_pointer);
self->streamCB();
}
MyClass::MyClass(void *userdata) {
// do whatever you need to do with userdata
// (...)
// and setup the callback at C level
set_stream_callback(&MyClass::Callback, (void *)this);
}
In your example, the int mid variable would become a property of that class, and thus be accessible from the callback implementation streamCB.

How to pass a Function pointer without exposing class details

I'm creating a library that needs to allow the user to set a callback function.
The interface of this library is as below:
// Viewer Class Interface Exposed to user
/////////////////////////////
#include "dataType_1.h"
#include "dataType_2.h"
class Viewer
{
void SetCallbackFuntion( dataType_1* (Func) (dataType_2* ) );
private:
dataType_1* (*CallbackFunction) (dataType_2* );
}
In a typical usage, the user needs to access an object of dataType_3 within the callback.
However, this object is only known only to his program, like below.
// User usage
#include "Viewer.h"
#include "dataType_3.h"
// Global Declaration needed
dataType_3* objectDataType3;
dataType_1* aFunction( dataType_2* a)
{
// An operation on object of type dataType_3
objectDataType3->DoSomething();
}
main()
{
Viewer* myViewer;
myViewer->SetCallbackFunction( &aFunction );
}
My Question is as follows:
How do I avoid using an ugly global variable for objectDataType3 ?
(objectDataType3 is part of libraryFoo and all the other objects dataType_1, dataType_2 & Viewer are part of libraryFooBar) Hence I would like them to remain as separate as possible.
Don't use C in C++.
Use an interface to represent the fact you want a notification.
If you want objects of type dataType_3 to be notified of an event that happens in the viewer then just make this type implement the interface then you can register the object directly with the viewer for notification.
// The interface
// Very close to your function pointer definition.
class Listener
{
public: virtual dataType_1* notify(dataType_2* param) = 0;
};
// Updated viewer to use the interface defineition rather than a pointer.
// Note: In the old days of C when you registered a callback you normally
// also registered some data that was passed to the callback
// (see pthread_create for example)
class Viewer
{
// Set (or Add) a listener.
void SetNotifier(Listener* l) { listener = l; }
// Now you can just inform all objects that are listening
// directly via the interface. (remember to check for NULL listener)
void NotifyList(dataType_2* data) { if (listener) { listener->notify(data); }
private:
Listener* listener;
};
int main()
{
dataType_3 objectDataType3; // must implement the Listener interface
Viewer viewer;
viewer.SetNotifier(&objectDataType3);
}
Use Boost.Function:
class Viewer
{
void SetCallbackFuntion(boost::function<datatype_1* (dataType_2*)> func);
private:
boost::function<datatype_1* (dataType_2*)> CallbackFunction;
}
Then use Boost.Bind to pass the member function pointer together with your object as the function.
If you don't want or can't use boost, the typical pattern around callback functions like this is that you can pass a "user data" value (mostly declared as void*) when registering the callback. This value is then passed to the callback function.
The usage then looks like this:
dataType_1* aFunction( dataType_2* a, void* user_ptr )
{
// Cast user_ptr to datatype_3
// We know it works because we passed it during set callback
datatype_3* objectDataType3 = reinterpret_cast<datatype_3*>(user_ptr);
// An operation on object of type dataType_3
objectDataType3->DoSomething();
}
main()
{
Viewer* myViewer;
dataType_3 objectDataType3; // No longer needs to be global
myViewer->SetCallbackFunction( &aFunction, &objectDataType3 );
}
The implementation on the other side only requires to save the void* along with the function pointer:
class Viewer
{
void SetCallbackFuntion( dataType_1* (Func) (dataType_2*, void*), void* user_ptr );
private:
dataType_1* (*CallbackFunction) (dataType_2*, void*);
void* user_ptr;
}
boost::/std:: function is the solution here. You can bind member functions to them, and in addition functors and lambdas, if you have a lambda compiler.
struct local {
datatype3* object;
local(datatype3* ptr)
: object(ptr) {}
void operator()() {
object->func();
}
};
boost::function<void()> func;
func = local(object);
func(); // calls object->func() by magic.
Something like this is simple to do:
class Callback
{
public:
virtual operator()()=0;
};
template<class T>
class ClassCallback
{
T* _classPtr;
typedef void(T::*fncb)();
fncb _cbProc;
public:
ClassCallback(T* classPtr,fncb cbProc):_classPtr(classPtr),_cbProc(cbProc){}
virtual operator()(){
_classPtr->*_cbProc();
}
};
Your Viewer class would take a callback, and call it using the easy syntax:
class Viewer
{
void SetCallbackFuntion( Callback* );
void OnCallCallback(){
m_cb->operator()();
}
}
Some other class would register the callback with the viewer by using the ClassCallback template specialization:
// User usage
#include "Viewer.h"
#include "dataType_3.h"
main()
{
Viewer* myViewer;
dataType_3 objectDataType3;
myViewer->SetCallbackFunction( new ClassCallback<dataType_3>(&objectDataType3,&dataType_3::DoSomething));
}
You're asking several questions mixed up in here and this is going to cause you lots of confusion in your answers.
I'm going to focus on your issue with dataType_3.
You state:
I would like to avoid declaring or
including dataType_3 in my library as
it has huge dependencies.
What you need to do is make an interface class for dataType_3 that gives the operations -- the footprint -- of dataType_3 without defining everything in it. You'll find tips on how to do that in this article (among other places). This will allow you to comfortably include a header that gives the footprint for dataType_3 without bringing in all of its dependencies. (If you've got dependencies in the public API you may have to reuse that trick for all of those as well. This can get tedious, but this is the price of having a poorly-designed API.)
Once you've got that, instead of passing in a function for callback consider having your "callback" instead be a class implementing a known interface. There are several advantages to doing this which you can find in the literature, but for your specific example there's a further advantage. You can inherit that interface complete with an instantiated dataType_3 object in the base class. This means that you only have to #include the dataType_3 interface specification and then use the dataType_3 instance provided for you by the "callback" framework.
If you have the option of forcing some form of constraints on Viewer, I would simply template that, i.e.
template <typename CallBackType>
class Viewer
{
public:
void SetCallbackFunctor(CallBackType& callback) { _callee = callback; }
void OnCallback()
{
if (_callee) (*_callee)(...);
}
private:
// I like references, but you can use pointers
boost::optional<CallBackType&> _callee;
};
Then in your dataType_3 implement the operator() to do as needed, to use.
int main(void)
{
dataType_3 objectDataType3;
// IMHO, I would construct with the objectDataType3, rather than separate method
// if you did that, you can hold a direct reference rather than pointer or boost::optional!
Viewer<dataType_3> viewer;
viewer.SetCallbackFunctor(objectDataType3);
}
No need for other interfaces, void* etc.

C++: static function wrapper that routes to member function?

I've tried all sorts of design approaches to solve this problem, but I just can't seem to get it right.
I need to expose some static functions to use as callback function to a C lib. However, I want the actual implementation to be non-static, so I can use virtual functions and reuse code in a base class. Such as:
class Callbacks {
static void MyCallBack() { impl->MyCallBackImpl(); }
...
class CallbackImplBase {
virtual void MyCallBackImpl() = 0;
However I try to solve this (Singleton, composition by letting Callbacks be contained in the implementor class, etc) I end up in a dead-end (impl usually ends up pointing to the base class, not the derived one).
I wonder if it is at all possible or if I'm stuck with creating some sort of helper functions instead of using inheritance?
Problem 1:
Though it may look and seem to work on your setup this is not guaranteed to work as the C++ ABI is not defined. So technically you can not use C++ static member functions as functions pointers to be used by C code.
Problem 2:
All C callacks (that I know of) allow you to pass user data back as a void*. You can use this as the pointer to your object that has the virtual method. BUT You must make sure you use dynamic_cast<>() to the base class (the one with the virtual method used in the callback) before it is converted into the void* otherwise the pointer at the other end may not be interpreted correctly (especially if there is multiple inheritance involved).
Problem 3:
Exceptions: C is not designed to work with exceptions (especially old C libraries with callbacks). So don't expect exceptions that escape your callback to provide anything meaningful to the caller (they are more likely to result in application termination).
Solution:
What you need to do is use extern "C" function as the callback that calls the virtual method on an object of know type and throws away all exceptions.
An example for the C pthread routines
#include <iostream>
extern "C" void* start_thread(void* data);
class Work
{
public:
virtual ~Work() {}
virtual void doWork() = 0;
};
/*
* To be used as a callback for C code this MUST be declared as
* with extern "C" linkage to make sure the calling code can
* correctly call it
*/
void* start_thread(void* data)
{
/*
* Use reinterpret_cast<>() because the only thing you know
* that you can do is cast back to a Work* pointer.
*
*/
Work* work = reinterpret_cast<Work*>(data);
try
{
work->doWork();
}
catch(...)
{
// Never let an exception escape a callback.
// As you are being called back from C code this would probably result
// in program termination as the C ABI does not know how to cope with
// exceptions and thus would not be able to unwind the call stack.
//
// An exception is if the C code had been built with a C++ compiler
// But if like pthread this is an existing C lib you are unlikely to get
// the results you expect.
}
return NULL;
}
class PrintWork: public Work
{
public:
virtual void doWork()
{
std::cout << "Hi \n";
}
};
int main()
{
pthread_t thread;
PrintWork printer;
/*
* Use dynamic_cast<>() here because you must make sure that
* the underlying routine receives a Work* pointer
*
* As it is working with a void* there is no way for the compiler
* to do this intrinsically so you must do it manually at this end
*/
int check = pthread_create(&thread,NULL,start_thread,dynamic_cast<Work*>(&printer));
if (check == 0)
{
void* result;
pthread_join(thread,&result);
}
}
It's possible. Perhaps there's a problem on how you're initializing the concrete implementation?
In fact, I remember one library that does something very similar to this. You might find it usefull to take a look at libxml++ source code. It's built on top of libxml, which is a C library.
libxml++ uses a struct of static functions to handle the callbacks. For customization, the design allows the user to provide (through virtual functions) his/her own implementations to which the callbacks are then forwarded. I guess this is pretty much your situation.
Something like the below. The singleton is in class Callback, the Instance member will return a statically allocated reference to a CallbackImpl class. This is a singleton because the reference will only be initialised once when the function is first called. Also, it must be a reference or a pointer otherwise the virtual function will not work.
class CallbackImplBase
{
public:
virtual void MyCallBackImpl() = 0;
};
class CallbackImpl : public CallbackImplBase
{
public:
void MyCallBackImpl()
{
std::cout << "MyCallBackImpl" << std::endl;
}
};
class Callback
{
public:
static CallbackImplBase & Instance()
{
static CallbackImpl instance;
return instance;
}
static void MyCallBack()
{
Instance().MyCallBackImpl();
}
};
extern "C" void MyCallBack()
{
Callback::MyCallBack();
}
Are any of the parameters passed to the callback function user defined? Is there any way you can attach a user defined value to data passed to these callbacks? I remember when I implemented a wrapper library for Win32 windows I used SetWindowLong() to attach a this pointer to the window handle which could be later retrieved in the callback function. Basically, you need to pack the this pointer somewhere so that you can retrieve it when the callback gets fired.
struct CALLBACKDATA
{
int field0;
int field1;
int field2;
};
struct MYCALLBACKDATA : public CALLBACKDATA
{
Callback* ptr;
};
registerCallback( Callback::StaticCallbackFunc, &myCallbackData, ... );
void Callback::StaticCallbackFunc( CALLBACKDATA* pData )
{
MYCALLBACKDATA* pMyData = (MYCALLBACKDATA*)pData;
Callback* pCallback = pMyData->ptr;
pCallback->virtualFunctionCall();
}