#include <iostream>
#include <tuple>
#include <type_traits>
using namespace std;
//* External type stubs
struct lua_State;
void* lua_touserdata(lua_State *, int) { return nullptr; }
int lua_upvalueindex(int) { return 0; }
int luaL_error(lua_State *, const char *) { return 0; }
struct Lua
{
lua_State *L;
template <typename T>
T* CheckPtr(int) { return nullptr; }
template <int, typename ...Args>
tuple<Args...> CheckArgs() { return {}; }
template <typename T>
void Push(T) {}
};
//*/
template <typename F>
class FunctionPointer
{
template <typename R, typename ...Args>
static R func_return( R(*)(Args...) )
{ return {}; }
using R_ = decltype( func_return( (F)nullptr ) );
struct void_type {};
public:
F f;
using R = typename conditional<is_void<R_>::value, void_type, R_>::type;
template <typename ...Args>
R Apply(tuple<Args...> &args)
{
cout << __PRETTY_FUNCTION__ << '\n';
return {};
}
};
template<typename R, typename ...Args>
struct Wrapper
{
using F = R (*)(Args...);
static int f (lua_State *L, F f)
{
Lua lua {L};
// Build a tuple of arguments.
auto args = lua.CheckArgs<1, Args...>();
// Grab the function pointer.
FunctionPointer<F> fp {f};
// Apply the function to the tuple.
if (is_void<R>::value)
{
fp.Apply(args);
return 0;
}
else
{
lua.Push( fp.Apply(args) );
return 1;
}
}
};
void func1(int) {}
lua_State* func2(Lua) { return nullptr; }
int main()
{
Wrapper<void, int> w1;
w1.f(nullptr, &func1);
Wrapper<lua_State*, Lua> w2;
w2.f(nullptr, &func2);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDx0eXBlX3RyYWl0cz4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCgovLyogRXh0ZXJuYWwgdHlwZSBzdHVicwpzdHJ1Y3QgbHVhX1N0YXRlOwp2b2lkKiBsdWFfdG91c2VyZGF0YShsdWFfU3RhdGUgKiwgaW50KSB7IHJldHVybiBudWxscHRyOyB9CmludCBsdWFfdXB2YWx1ZWluZGV4KGludCkgeyByZXR1cm4gMDsgfQppbnQgbHVhTF9lcnJvcihsdWFfU3RhdGUgKiwgY29uc3QgY2hhciAqKSB7IHJldHVybiAwOyB9CnN0cnVjdCBMdWEKewogIGx1YV9TdGF0ZSAqTDsKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KICBUKiBDaGVja1B0cihpbnQpIHsgcmV0dXJuIG51bGxwdHI7IH0KICB0ZW1wbGF0ZSA8aW50LCB0eXBlbmFtZSAuLi5BcmdzPgogIHR1cGxlPEFyZ3MuLi4+IENoZWNrQXJncygpIHsgcmV0dXJuIHt9OyB9CiAgdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CiAgdm9pZCBQdXNoKFQpIHt9Cn07Ci8vKi8KCnRlbXBsYXRlIDx0eXBlbmFtZSBGPgpjbGFzcyBGdW5jdGlvblBvaW50ZXIKewogIHRlbXBsYXRlIDx0eXBlbmFtZSBSLCB0eXBlbmFtZSAuLi5BcmdzPgogIHN0YXRpYyBSIGZ1bmNfcmV0dXJuKCBSKCopKEFyZ3MuLi4pICkKICB7IHJldHVybiB7fTsgfQogIHVzaW5nIFJfID0gZGVjbHR5cGUoIGZ1bmNfcmV0dXJuKCAoRiludWxscHRyICkgKTsKICBzdHJ1Y3Qgdm9pZF90eXBlIHt9OwoKcHVibGljOgogIEYgZjsKICB1c2luZyBSID0gdHlwZW5hbWUgY29uZGl0aW9uYWw8aXNfdm9pZDxSXz46OnZhbHVlLCB2b2lkX3R5cGUsIFJfPjo6dHlwZTsKICB0ZW1wbGF0ZSA8dHlwZW5hbWUgLi4uQXJncz4KICBSIEFwcGx5KHR1cGxlPEFyZ3MuLi4+ICZhcmdzKQogIHsgCiAgICBjb3V0IDw8IF9fUFJFVFRZX0ZVTkNUSU9OX18gPDwgJ1xuJzsKICAgIHJldHVybiB7fTsKICB9Cn07CgoKdGVtcGxhdGU8dHlwZW5hbWUgUiwgdHlwZW5hbWUgLi4uQXJncz4Kc3RydWN0IFdyYXBwZXIKewogIHVzaW5nIEYgPSBSICgqKShBcmdzLi4uKTsKICAKICBzdGF0aWMgaW50IGYgKGx1YV9TdGF0ZSAqTCwgRiBmKQogIHsKICAgIEx1YSBsdWEge0x9OwoKICAgIC8vIEJ1aWxkIGEgdHVwbGUgb2YgYXJndW1lbnRzLgogICAgYXV0byBhcmdzID0gbHVhLkNoZWNrQXJnczwxLCBBcmdzLi4uPigpOwogIAogICAgLy8gR3JhYiB0aGUgZnVuY3Rpb24gcG9pbnRlci4KICAgIEZ1bmN0aW9uUG9pbnRlcjxGPiBmcCB7Zn07CiAgICAvLyBBcHBseSB0aGUgZnVuY3Rpb24gdG8gdGhlIHR1cGxlLgogICAgaWYgKGlzX3ZvaWQ8Uj46OnZhbHVlKQogICAgewogICAgICBmcC5BcHBseShhcmdzKTsKICAgICAgcmV0dXJuIDA7CiAgICB9CiAgICBlbHNlCiAgICB7CiAgICAgIGx1YS5QdXNoKCBmcC5BcHBseShhcmdzKSApOwogICAgICByZXR1cm4gMTsKICAgIH0KICB9Cn07CgoKdm9pZCAgICAgICAgZnVuYzEoaW50KSB7fQpsdWFfU3RhdGUqICBmdW5jMihMdWEpIHsgcmV0dXJuIG51bGxwdHI7IH0KCmludCBtYWluKCkKewogIFdyYXBwZXI8dm9pZCwgaW50PiB3MTsKICB3MS5mKG51bGxwdHIsICZmdW5jMSk7CgogIFdyYXBwZXI8bHVhX1N0YXRlKiwgTHVhPiB3MjsKICB3Mi5mKG51bGxwdHIsICZmdW5jMik7Cn0K