Created
June 24, 2015 18:35
-
-
Save krypt-n/a3ac2c6fe731a33f4580 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <utility> | |
#include <iostream> | |
/** | |
* Trampolines to methods for C-style callbacks. | |
* | |
* The void* / callback data is the instance you want the method | |
* called on. | |
*/ | |
template<typename T, typename ...Types> | |
struct trampoline { | |
/** | |
* Trampoline for callbacks with void* argument at the end of the | |
* argument list | |
*/ | |
template<void (T::*ptmf)(Types...)> | |
static | |
void postvoid(Types... args, void *object) { | |
T *o = static_cast<T*>(object); | |
(o->*ptmf)(std::forward<Types>(args)...); | |
} | |
/** | |
* Trampoline for callbacks with void* as the first argument | |
*/ | |
template<void (T::*ptmf)(Types...)> | |
static | |
void prevoid(void *object, Types... args) { | |
T *o = static_cast<T*>(object); | |
(o->*ptmf)(std::forward<Types>(args)...); | |
} | |
}; | |
template<typename T, typename Fn, Fn ptmf, typename ...Types> | |
void callback(Types... args, void *object) { | |
T *o = static_cast<T*>(object); | |
(o->*ptmf)(std::forward<Types>(args)...); | |
} | |
#define CALLBACK(T, FUNC, ...) callback<T, decltype(FUNC), FUNC, __VA_ARGS__> | |
void c_style_callback_caller(void (*cb)(int, void*), void *data) | |
{ | |
cb(42, data); | |
} | |
void c_style_callback_caller_pre(void (*cb)(void*, int), void *data) | |
{ | |
cb(data, 41); | |
} | |
class C { | |
public: | |
void p0() { | |
std::cout << "p0()\n"; | |
} | |
void p1(int x) { | |
std::cout << "p1(" << x << ")\n"; | |
} | |
static | |
void classic_cb_p1(int x, void *object) { | |
C *c = static_cast<C*>(object); | |
c->p1(x); | |
} | |
}; | |
int main() { | |
C inst; | |
// both produce EXACTLY the same code | |
c_style_callback_caller(trampoline<C, int>::postvoid<&C::p1>, &inst); | |
c_style_callback_caller(CALLBACK(C, &C::p1, int), &inst); | |
c_style_callback_caller(&C::classic_cb_p1, &inst); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment