#include <iostream>
#include <cstdlib>
#include <functional>
// C library with some callbacks
typedef void (*CallbackTypeOne)(void* userdata, double arg1);
typedef void (*CallbackTypeTwo)(void* userdata, int arg1);
typedef void (*CallbackTypeThree)(void* userdata, int arg1, float arg2);
typedef void(*GenericCallback)();
void registerAndCallCallback(int typeID, GenericCallback callback, void* userdata)
{
switch (typeID) {
case 0: ((CallbackTypeOne)callback)(userdata, 3.14); break;
case 1: ((CallbackTypeTwo)callback)(userdata, 42); break;
case 2: ((CallbackTypeThree)callback)(userdata, 42, 3.14f); break;
};
}
// C++ app using the above library
template <const size_t TypeID, typename T, typename RetType, typename... Args>
struct FunctionFactory
{
public:
static void bind(RetType(T::*f)(Args...)) {
instance().fn_ = [f](T* t, Args&&... args) {
return (t->*f)(std::forward<Args>(args)...);
};
}
static RetType invoke(void* userdata, Args... args) {
T * t = reinterpret_cast<T*>(userdata);
return instance().fn_(t, args...);
}
typedef decltype(&FunctionFactory::invoke) pointer_type;
static pointer_type ptr() {
return &invoke;
}
private:
static FunctionFactory & instance() {
static FunctionFactory inst_;
return inst_;
}
FunctionFactory() = default;
std::function<RetType(T*, Args...)> fn_;
};
template <const size_t TypeID, typename T, typename RetType, typename... Args>
typename FunctionFactory<TypeID, T, RetType, Args...>::pointer_type
getFunctionPtr(RetType(T::*f)(Args...))
{
FunctionFactory<TypeID, T, RetType, Args...>::bind(f);
return FunctionFactory<TypeID, T, RetType, Args...>::ptr();
}
class MyClass
{
public:
MyClass() {
registerAndCallCallback(0, reinterpret_cast<GenericCallback>(getFunctionPtr<0>(&MyClass::callbackOne)), this);
registerAndCallCallback(1, reinterpret_cast<GenericCallback>(getFunctionPtr<1>(&MyClass::callbackTwo)), this);
registerAndCallCallback(2, reinterpret_cast<GenericCallback>(getFunctionPtr<2>(&MyClass::callbackThree)), this);
}
void callbackOne(double arg1) { std::cout << "callback 1 called: " << arg1 << std::endl; }
void callbackTwo(int arg1) { std::cout << "callback 2 called: " << arg1 << std::endl; }
void callbackThree(int arg1, float arg2) { std:: cout << "callback 3 called: " << arg1 << ", " << arg2 << std::endl; }
};
int main()
{
MyClass myclass;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y3N0ZGxpYj4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CgovLyBDIGxpYnJhcnkgd2l0aCBzb21lIGNhbGxiYWNrcwoKdHlwZWRlZiB2b2lkICgqQ2FsbGJhY2tUeXBlT25lKSh2b2lkKiB1c2VyZGF0YSwgZG91YmxlIGFyZzEpOwp0eXBlZGVmIHZvaWQgKCpDYWxsYmFja1R5cGVUd28pKHZvaWQqIHVzZXJkYXRhLCBpbnQgYXJnMSk7CnR5cGVkZWYgdm9pZCAoKkNhbGxiYWNrVHlwZVRocmVlKSh2b2lkKiB1c2VyZGF0YSwgaW50IGFyZzEsIGZsb2F0IGFyZzIpOwoKdHlwZWRlZiB2b2lkKCpHZW5lcmljQ2FsbGJhY2spKCk7Cgp2b2lkIHJlZ2lzdGVyQW5kQ2FsbENhbGxiYWNrKGludCB0eXBlSUQsIEdlbmVyaWNDYWxsYmFjayBjYWxsYmFjaywgdm9pZCogdXNlcmRhdGEpCnsKICAgIHN3aXRjaCAodHlwZUlEKSB7CiAgICBjYXNlIDA6ICgoQ2FsbGJhY2tUeXBlT25lKWNhbGxiYWNrKSh1c2VyZGF0YSwgMy4xNCk7IGJyZWFrOwogICAgY2FzZSAxOiAoKENhbGxiYWNrVHlwZVR3byljYWxsYmFjaykodXNlcmRhdGEsIDQyKTsgYnJlYWs7CiAgICBjYXNlIDI6ICgoQ2FsbGJhY2tUeXBlVGhyZWUpY2FsbGJhY2spKHVzZXJkYXRhLCA0MiwgMy4xNGYpOyBicmVhazsKICAgIH07Cn0KCi8vIEMrKyBhcHAgdXNpbmcgdGhlIGFib3ZlIGxpYnJhcnkKCnRlbXBsYXRlIDxjb25zdCBzaXplX3QgVHlwZUlELCB0eXBlbmFtZSBULCB0eXBlbmFtZSBSZXRUeXBlLCB0eXBlbmFtZS4uLiBBcmdzPgpzdHJ1Y3QgRnVuY3Rpb25GYWN0b3J5CnsKcHVibGljOgogICAgc3RhdGljIHZvaWQgYmluZChSZXRUeXBlKFQ6OipmKShBcmdzLi4uKSkgewogICAgICAgIGluc3RhbmNlKCkuZm5fID0gW2ZdKFQqIHQsIEFyZ3MmJi4uLiBhcmdzKSB7CiAgICAgICAgICAgIHJldHVybiAodC0+KmYpKHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7CiAgICAgICAgfTsKICAgIH0KCiAgICBzdGF0aWMgUmV0VHlwZSBpbnZva2Uodm9pZCogdXNlcmRhdGEsIEFyZ3MuLi4gYXJncykgewogICAgICAgIFQgKiB0ID0gcmVpbnRlcnByZXRfY2FzdDxUKj4odXNlcmRhdGEpOwogICAgICAgIHJldHVybiBpbnN0YW5jZSgpLmZuXyh0LCBhcmdzLi4uKTsKICAgIH0KCiAgICB0eXBlZGVmIGRlY2x0eXBlKCZGdW5jdGlvbkZhY3Rvcnk6Omludm9rZSkgcG9pbnRlcl90eXBlOwogICAgc3RhdGljIHBvaW50ZXJfdHlwZSBwdHIoKSB7CiAgICAgICAgcmV0dXJuICZpbnZva2U7CiAgICB9Cgpwcml2YXRlOgogICAgc3RhdGljIEZ1bmN0aW9uRmFjdG9yeSAmIGluc3RhbmNlKCkgewogICAgICAgIHN0YXRpYyBGdW5jdGlvbkZhY3RvcnkgaW5zdF87CiAgICAgICAgcmV0dXJuIGluc3RfOwogICAgfQoKICAgIEZ1bmN0aW9uRmFjdG9yeSgpID0gZGVmYXVsdDsKCiAgICBzdGQ6OmZ1bmN0aW9uPFJldFR5cGUoVCosIEFyZ3MuLi4pPiBmbl87Cn07Cgp0ZW1wbGF0ZSA8Y29uc3Qgc2l6ZV90IFR5cGVJRCwgdHlwZW5hbWUgVCwgdHlwZW5hbWUgUmV0VHlwZSwgdHlwZW5hbWUuLi4gQXJncz4KdHlwZW5hbWUgRnVuY3Rpb25GYWN0b3J5PFR5cGVJRCwgVCwgUmV0VHlwZSwgQXJncy4uLj46OnBvaW50ZXJfdHlwZQpnZXRGdW5jdGlvblB0cihSZXRUeXBlKFQ6OipmKShBcmdzLi4uKSkKewogICAgRnVuY3Rpb25GYWN0b3J5PFR5cGVJRCwgVCwgUmV0VHlwZSwgQXJncy4uLj46OmJpbmQoZik7CiAgICByZXR1cm4gRnVuY3Rpb25GYWN0b3J5PFR5cGVJRCwgVCwgUmV0VHlwZSwgQXJncy4uLj46OnB0cigpOwp9CgpjbGFzcyBNeUNsYXNzCnsKcHVibGljOgogICAgTXlDbGFzcygpIHsKICAgICAgICByZWdpc3RlckFuZENhbGxDYWxsYmFjaygwLCByZWludGVycHJldF9jYXN0PEdlbmVyaWNDYWxsYmFjaz4oZ2V0RnVuY3Rpb25QdHI8MD4oJk15Q2xhc3M6OmNhbGxiYWNrT25lKSksIHRoaXMpOwogICAgICAgIHJlZ2lzdGVyQW5kQ2FsbENhbGxiYWNrKDEsIHJlaW50ZXJwcmV0X2Nhc3Q8R2VuZXJpY0NhbGxiYWNrPihnZXRGdW5jdGlvblB0cjwxPigmTXlDbGFzczo6Y2FsbGJhY2tUd28pKSwgdGhpcyk7CiAgICAgICAgcmVnaXN0ZXJBbmRDYWxsQ2FsbGJhY2soMiwgcmVpbnRlcnByZXRfY2FzdDxHZW5lcmljQ2FsbGJhY2s+KGdldEZ1bmN0aW9uUHRyPDI+KCZNeUNsYXNzOjpjYWxsYmFja1RocmVlKSksIHRoaXMpOwogICAgfQoKICAgIHZvaWQgY2FsbGJhY2tPbmUoZG91YmxlIGFyZzEpIHsgc3RkOjpjb3V0IDw8ICJjYWxsYmFjayAxIGNhbGxlZDogIiA8PCBhcmcxIDw8IHN0ZDo6ZW5kbDsgfQogICAgdm9pZCBjYWxsYmFja1R3byhpbnQgYXJnMSkgeyBzdGQ6OmNvdXQgPDwgImNhbGxiYWNrIDIgY2FsbGVkOiAiIDw8IGFyZzEgPDwgc3RkOjplbmRsOyB9CiAgICB2b2lkIGNhbGxiYWNrVGhyZWUoaW50IGFyZzEsIGZsb2F0IGFyZzIpIHsgc3RkOjogY291dCA8PCAiY2FsbGJhY2sgMyBjYWxsZWQ6ICIgPDwgYXJnMSA8PCAiLCAiIDw8IGFyZzIgPDwgc3RkOjplbmRsOyB9Cn07CgppbnQgbWFpbigpCnsKICAgIE15Q2xhc3MgbXljbGFzczsKICAgIHJldHVybiAwOwp9Cg==