#include <iostream>
using namespace std;
#include <map>
template<typename T>
class Base
{
public:
typedef void (T::*PFunc)(void);
typedef void (*PHandler)(void*);
using method_map_t = map< string, PHandler >;
static method_map_t& methods( ) {
static method_map_t* map_of_methods{};
if( ! map_of_methods ) map_of_methods = new method_map_t;
return *map_of_methods;
}
static void register_method( string name, PHandler handler ) {
methods()[name] = handler;
}
// generic trampoline
template<PFunc sig>
static void Handler( void* pInstance ) {
T* f = reinterpret_cast<T*>(pInstance);
(f ->* sig)();
}
};
class Final : Base<Final>
{
public:
void Foo(){cout<<"got foo";}
void Bar(){cout<<"got bar";}
static void init(){
// register_method populates a table of "extern C" function pointers.
register_method( "foo", static_cast<PHandler>( &Handler<&Final::Foo> ) );
register_method( "bar", static_cast<PHandler>( &Handler<&Final::Bar> ) );
}
};
void InvokeFromC(void* inst, string name) {
Base<Final>::PHandler h = Base<Final>::methods()[name];
(*h)(inst);
}
int main() {
Final* f = new Final{};
f->init();
// simulate invoking from C
InvokeFromC( f, "foo" );
// your code goes here
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKI2luY2x1ZGUgPG1hcD4KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CmNsYXNzIEJhc2UKewpwdWJsaWM6ICAgIAogICAgdHlwZWRlZiB2b2lkIChUOjoqUEZ1bmMpKHZvaWQpOwogICAgdHlwZWRlZiB2b2lkICgqUEhhbmRsZXIpKHZvaWQqKTsKCiAgICB1c2luZyBtZXRob2RfbWFwX3QgPSBtYXA8IHN0cmluZywgUEhhbmRsZXIgPjsKICAgIHN0YXRpYyBtZXRob2RfbWFwX3QmIG1ldGhvZHMoICkgewogICAgICAgIHN0YXRpYyBtZXRob2RfbWFwX3QqIG1hcF9vZl9tZXRob2Rze307CiAgICAgICAgaWYoICEgbWFwX29mX21ldGhvZHMgKSBtYXBfb2ZfbWV0aG9kcyA9IG5ldyBtZXRob2RfbWFwX3Q7CiAgICAgICAgcmV0dXJuICptYXBfb2ZfbWV0aG9kczsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCByZWdpc3Rlcl9tZXRob2QoIHN0cmluZyBuYW1lLCBQSGFuZGxlciBoYW5kbGVyICkgewogICAgICAgIG1ldGhvZHMoKVtuYW1lXSA9IGhhbmRsZXI7CiAgICB9CgogICAgLy8gZ2VuZXJpYyB0cmFtcG9saW5lCiAgICB0ZW1wbGF0ZTxQRnVuYyBzaWc+CiAgICBzdGF0aWMgdm9pZCBIYW5kbGVyKCB2b2lkKiBwSW5zdGFuY2UgKSB7CiAgICAgICAgVCogZiA9IHJlaW50ZXJwcmV0X2Nhc3Q8VCo+KHBJbnN0YW5jZSk7CiAgICAgICAgKGYgLT4qIHNpZykoKTsKICAgIH0KfTsKCmNsYXNzIEZpbmFsIDogQmFzZTxGaW5hbD4KewpwdWJsaWM6CiAgICB2b2lkIEZvbygpe2NvdXQ8PCJnb3QgZm9vIjt9CiAgICB2b2lkIEJhcigpe2NvdXQ8PCJnb3QgYmFyIjt9CiAgICAKICAgIHN0YXRpYyB2b2lkIGluaXQoKXsKICAgICAgICAvLyByZWdpc3Rlcl9tZXRob2QgcG9wdWxhdGVzIGEgdGFibGUgb2YgImV4dGVybiBDIiBmdW5jdGlvbiBwb2ludGVycy4KICAgICAgICByZWdpc3Rlcl9tZXRob2QoICJmb28iLCBzdGF0aWNfY2FzdDxQSGFuZGxlcj4oICZIYW5kbGVyPCZGaW5hbDo6Rm9vPiApICk7CiAgICAgICAgcmVnaXN0ZXJfbWV0aG9kKCAiYmFyIiwgc3RhdGljX2Nhc3Q8UEhhbmRsZXI+KCAmSGFuZGxlcjwmRmluYWw6OkJhcj4gKSApOwogICAgfQp9OwoKdm9pZCBJbnZva2VGcm9tQyh2b2lkKiBpbnN0LCBzdHJpbmcgbmFtZSkgewoJQmFzZTxGaW5hbD46OlBIYW5kbGVyIGggPSBCYXNlPEZpbmFsPjo6bWV0aG9kcygpW25hbWVdOwoJKCpoKShpbnN0KTsKfQoKaW50IG1haW4oKSB7CglGaW5hbCogZiA9IG5ldyBGaW5hbHt9OwoJZi0+aW5pdCgpOwoJLy8gc2ltdWxhdGUgaW52b2tpbmcgZnJvbSBDIAoJSW52b2tlRnJvbUMoIGYsICJmb28iICk7CgkKCS8vIHlvdXIgY29kZSBnb2VzIGhlcmUKCXJldHVybiAwOwp9