1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /***** * How to use a non-static member function as a callback function * by Shane Beasley <sbeasley@acm.org> ***** * Scenario: You're using an event-driven library which was written in C -- at * least, it was written for use by C programmers. Whenever an event occurs (the * mouse moves, a network packet comes off the wire, the user opens the CD-ROM * drive, and so on), the library calls a function which you provided to handle * the event. If you were writing C, this would be very cut-and-dry; the program * expects a function with a certain signature, you provide it, and everyone's * happy. * * The trouble is that you're currently writing object-oriented C++, and instead * of a normal callback function, you need the library to call a member function * on an object. You try passing a member function to the library, but it doesn't * compile, and for good reason -- two reasons, actually. First, C doesn't know * anything about member functions, let alone how to call them. Specifically, * your average C++ member function requires at least two components, the * function itself and an object upon which to call it: C functions are called * like f(x, y), but C++ member functions are called x.f(y). Second, C++ member * function pointers are generally bigger than conventional member functions -- * perhaps three times as large -- because of extra information required for * resolving virtual function calls at run-time. * * The solution, then, needs to be able to tell C how to call a C++ member * function, and it needs to have a normal-sized function pointer. How about a * normal function which calls a C++ member function? :) *****/ //////////////////////////////////////////////////////////////////////////////// /* The event-driven C library in question looks something like this: */ typedef void (*callback_function) (int event_code, void *data); void on_event (callback_function f, void *data); // The goal is as follows: // - main() will have an instance of this class. // - we want to call a member function on this instance when an event occurs. class EventHandler { public: void handle (int eventCode); }; // Solution: a callback function which calls the desired member function on the // given EventHandler object. void call_member (int eventCode, void *data) { static_cast<EventHandler *>(data)->handle(eventCode); } // Putting it all together... int main () { EventHandler instance; on_event(&call_member, &instance); } |