/////////////////////////////////////////////////////////////////////////////// // This source file is part of the LuaPlus source distribution and is Copyright // 2001-2012 by Joshua C. Jensen (jjensen@workspacewhiz.com). // // The latest version may be obtained from http://luaplus.org/. // // The code presented in this file may be used in any environment it is // acceptable to use Lua. /////////////////////////////////////////////////////////////////////////////// #ifndef LUAPLUS__LUAPLUSCD_H #define LUAPLUS__LUAPLUSCD_H extern "C" { #include "lua.h" #include "lauxlib.h" } #include #include // LuaPlus Call Dispatcher namespace LPCD { struct LuaLightUserdata { LuaLightUserdata(const void* value) : m_value(value) { } const void* m_value; }; struct LuaUserdata { LuaUserdata(const void* value) : m_value(value) { } const void* m_value; }; struct LuaNil { }; template struct Type { }; // bool types template<> struct Type { static inline void Push(lua_State* L, bool value) { lua_pushboolean(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TBOOLEAN; } static inline bool Get(lua_State* L, int idx) { return lua_toboolean(L, idx) != 0; } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // char types template<> struct Type { static inline void Push(lua_State* L, char value) { lua_pushinteger(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline char Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // unsigned char types template<> struct Type { static inline void Push(lua_State* L, unsigned char value) { lua_pushinteger(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline unsigned char Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // short types template<> struct Type { static inline void Push(lua_State* L, short value) { lua_pushinteger(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline short Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // unsigned short types template<> struct Type { static inline void Push(lua_State* L, unsigned short value) { lua_pushinteger(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline unsigned short Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // int types template<> struct Type { static inline void Push(lua_State* L, int value) { lua_pushinteger(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline int Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // unsigned int types template<> struct Type { static inline void Push(lua_State* L, unsigned int value) { lua_pushinteger(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline unsigned int Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // long types template<> struct Type { static inline void Push(lua_State* L, long value) { lua_pushinteger(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline long Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // unsigned long types template<> struct Type { static inline void Push(lua_State* L, unsigned long value) { lua_pushinteger(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline unsigned long Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; #if defined(_WIN64) // size_t types template<> struct Type { static inline void Push(lua_State* L, size_t value) { lua_pushinteger(L, (lua_Integer)value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline size_t Get(lua_State* L, int idx) { return static_cast(lua_tointeger(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; #endif // _WIN64 // float types template<> struct Type { static inline void Push(lua_State* L, float value) { lua_pushnumber(L, (lua_Number)value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline float Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // double types template<> struct Type { static inline void Push(lua_State* L, double value) { lua_pushnumber(L, (lua_Number)value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline double Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // int types template<> struct Type { static inline void Push(lua_State* L, lua_Integer value) { lua_pushinteger(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TNUMBER; } static inline int Get(lua_State* L, int idx) { return static_cast(lua_tonumber(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; // character pointer types template<> struct Type { static inline void Push(lua_State* L, const char* value) { lua_pushstring(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TSTRING; } static inline const char* Get(lua_State* L, int idx) { return static_cast(lua_tostring(L, idx)); } }; template<> struct Type : public Type {}; // character array types template struct Type { static inline void Push(lua_State* L, const char value[NUM_CHARS]) { lua_pushstring(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TSTRING; } static inline const char* Get(lua_State* L, int idx) { return static_cast(lua_tostring(L, idx)); } }; template struct Type { static inline void Push(lua_State* L, const char value[NUM_CHARS]) { lua_pushstring(L, value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TSTRING; } static inline const char* Get(lua_State* L, int idx) { return static_cast(lua_tostring(L, idx)); } }; // nil type template<> struct Type { static inline void Push(lua_State* L, const LuaNil& value) { lua_pushnil(L); } static inline bool Match(lua_State* L, int idx) { return true; } static inline LuaNil Get(lua_State* L, int idx) { (void)L, (void)idx; return LuaNil(); } }; // c function type template<> struct Type { static inline void Push(lua_State* L, const lua_CFunction value) { lua_pushcclosure(L, value, 0); } static inline bool Match(lua_State* L, int idx) { return true; } static inline lua_CFunction Get(lua_State* L, int idx) { return static_cast(lua_tocfunction(L, idx)); } }; // void types template<> struct Type { static inline void Push(lua_State* L, const void* value) { lua_pushlightuserdata(L, (void*)value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TLIGHTUSERDATA; } static inline void* Get(lua_State* L, int idx) { return static_cast(lua_touserdata(L, idx)); } }; template<> struct Type : public Type {}; // light userdata type template<> struct Type { static inline void Push(lua_State* L, const LuaLightUserdata& value) { lua_pushlightuserdata(L, (void*)value.m_value); } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TLIGHTUSERDATA; } static inline void* Get(lua_State* L, int idx) { return static_cast(lua_touserdata(L, idx)); } }; // userdata types template<> struct Type { static inline void Push(lua_State* L, LuaUserdata value) { *(void **)(lua_newuserdata(L, sizeof(void *))) = (void*)value.m_value; } static inline bool Match(lua_State* L, int idx) { return lua_type(L, idx) == LUA_TUSERDATA; } static inline void* Get(lua_State* L, int idx) { return static_cast(lua_touserdata(L, idx)); } }; template<> struct Type : public Type {}; template<> struct Type : public Type {}; inline void Push(lua_State* L, const char* value, int len) { lua_pushlstring(L, value, len); } // inline void Get(TypeWrapper, lua_State*, int) // { } // inline lua_State* Get(TypeWrapper, lua_State* L, int /*idx*/) // { return L; } // inline bool Match(TypeWrapper, lua_State* L, int idx) // { return lua_type(L, idx) == LUA_TNONE; } ////////////////////////////////////////////////////////////////////////// #define luaL_argassert(arg, _index_) if (!Type::Match(L, _index_)) \ luaL_argerror(L, _index_, "bad argument") template struct ReturnSpecialization { static int Call(RT (*func)(), lua_State* L, int /*index*/) { RT ret = func(); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1), lua_State* L, int index) { luaL_argassert(1, index + 0); RT ret = func( Type::Get(L, index + 0) ); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1, P2), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); RT ret = func( Type::Get(L, index + 0), Type::Get(L, index + 1) ); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1, P2, P3), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); RT ret = func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2) ); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1, P2, P3, P4), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); RT ret = func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3) ); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1, P2, P3, P4, P5), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); RT ret = func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4) ); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); RT ret = func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5) ); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); RT ret = func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6) ); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); RT ret = func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7) ); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); RT ret = func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8) ); Type::Push(L, ret); return 1; } template static int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); luaL_argassert(10, index + 9); RT ret = func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8), Type::Get(L, index + 9) ); Type::Push(L, ret); return 1; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// template static int Call(Callee& callee, RT (Callee::*func)(), lua_State* L, int /*index*/) { RT ret = (callee.*func)(); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)() const, lua_State* L, int /*index*/) { RT ret = (callee.*func)(); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1), lua_State* L, int index) { luaL_argassert(1, index + 0); RT ret = (callee.*func)( Type::Get(L, index + 0) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1) const, lua_State* L, int index) { luaL_argassert(1, index + 0); RT ret = (callee.*func)( Type::Get(L, index + 0) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); luaL_argassert(10, index + 9); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8), Type::Get(L, index + 9) ); Type::Push(L, ret); return 1; } template static int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); luaL_argassert(10, index + 9); RT ret = (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8), Type::Get(L, index + 9) ); Type::Push(L, ret); return 1; } }; template<> struct ReturnSpecialization { static int Call(void (*func)(), lua_State* L, int /*index*/) { (void)L; func(); return 0; } template static int Call(void (*func)(P1), lua_State* L, int index) { luaL_argassert(1, index + 0); func( Type::Get(L, index + 0) ); return 0; } template static int Call(void (*func)(P1, P2), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); func( Type::Get(L, index + 0), Type::Get(L, index + 1) ); return 0; } template static int Call(void (*func)(P1, P2, P3), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2) ); return 0; } template static int Call(void (*func)(P1, P2, P3, P4), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3) ); return 0; } template static int Call(void (*func)(P1, P2, P3, P4, P5), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4) ); return 0; } template static int Call(void (*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5) ); return 0; } template static int Call(void (*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6) ); return 0; } template static int Call(void (*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7) ); return 0; } template static int Call(void (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8) ); return 0; } template static int Call(void (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); luaL_argassert(10, index + 9); func( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8), Type::Get(L, index + 9) ); return 0; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// template static int Call(Callee& callee, void (Callee::*func)(), lua_State* /*L*/, int /*index*/) { (callee.*func)(); return 0; } template static int Call(Callee& callee, void (Callee::*func)() const, lua_State* /*L*/, int /*index*/) { (callee.*func)(); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1), lua_State* L, int index) { luaL_argassert(1, index + 0); (callee.*func)( Type::Get(L, index + 0) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1) const, lua_State* L, int index) { luaL_argassert(1, index + 0); (callee.*func)( Type::Get(L, index + 0) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); luaL_argassert(10, index + 9); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8), Type::Get(L, index + 9) ); return 0; } template static int Call(Callee& callee, void (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) const, lua_State* L, int index) { luaL_argassert(1, index + 0); luaL_argassert(2, index + 1); luaL_argassert(3, index + 2); luaL_argassert(4, index + 3); luaL_argassert(5, index + 4); luaL_argassert(6, index + 5); luaL_argassert(7, index + 6); luaL_argassert(8, index + 7); luaL_argassert(9, index + 8); luaL_argassert(10, index + 9); (callee.*func)( Type::Get(L, index + 0), Type::Get(L, index + 1), Type::Get(L, index + 2), Type::Get(L, index + 3), Type::Get(L, index + 4), Type::Get(L, index + 5), Type::Get(L, index + 6), Type::Get(L, index + 7), Type::Get(L, index + 8), Type::Get(L, index + 9) ); return 0; } }; template int Call(RT (*func)(), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1, P2), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1, P2, P3), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1, P2, P3, P4), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1, P2, P3, P4, P5), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(RT (*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) { return ReturnSpecialization::Call(func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)() const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10), lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } template int Call(Callee& callee, RT (Callee::*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) const, lua_State* L, int index) { return ReturnSpecialization::Call(callee, func, L, index); } inline unsigned char* GetFirstUpvalueAsUserdata(lua_State* L) { void* buffer; #ifndef FAST_DISPATCH buffer = lua_touserdata(L, lua_upvalueindex(1)); #else // FAST_DISPATCH #endif // FAST_DISPATCH return (unsigned char*)buffer; } // The Helper class is needed for less fortunate compiler template implementations. template class DirectCallFunctionDispatchHelper { public: static inline int DirectCallFunctionDispatcher(lua_State* L) { unsigned char* buffer = GetFirstUpvalueAsUserdata(L); return Call(*(Func*)(buffer), L, 1); } }; template class DirectCallMemberDispatcherHelper { public: static inline int DirectCallMemberDispatcher(lua_State* L) { unsigned char* buffer = GetFirstUpvalueAsUserdata(L); return Call(**(Callee**)buffer, *(Func*)(buffer + sizeof(Callee*)), L, 1); } }; inline int lua_StateFunctionDispatcher(lua_State* L) { typedef int (*Functor)(lua_State*); unsigned char* buffer = GetFirstUpvalueAsUserdata(L); Functor& func = *(Functor*)(buffer); return (*func)(L); } template class lua_StateMemberDispatcherHelper { public: static inline int lua_StateMemberDispatcher(lua_State* L) { typedef int (Callee::*Functor)(lua_State*); unsigned char* buffer = GetFirstUpvalueAsUserdata(L); Callee& callee = **(Callee**)buffer; Functor& func = *(Functor*)(buffer + sizeof(Callee*)); return (callee.*func)(L); } }; } // namespace LPCD template inline void lpcd_pushdirectclosure(lua_State* L, Func func, unsigned int nupvalues = 0) { unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func)); memcpy(buffer, &func, sizeof(func)); lua_insert(L, -1 - (int)nupvalues); lua_pushcclosure(L, LPCD::DirectCallFunctionDispatchHelper::DirectCallFunctionDispatcher, nupvalues + 1); } template inline void lpcd_pushdirectclosure(lua_State* L, const Callee& callee, Func func, unsigned int nupvalues = 0) { unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(Callee*) + sizeof(func)); const void* pCallee = &callee; memcpy(buffer, &pCallee, sizeof(Callee*)); memcpy(buffer + sizeof(Callee*), &func, sizeof(func)); lua_insert(L, -1 - (int)nupvalues); lua_pushcclosure(L, LPCD::DirectCallMemberDispatcherHelper::DirectCallMemberDispatcher, nupvalues + 1); } inline void lpcd_pushfunctorclosure(lua_State* L, int (*func)(lua_State*), unsigned int nupvalues = 0) { unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func)); memcpy(buffer, &func, sizeof(func)); lua_insert(L, -1 - (int)nupvalues); lua_pushcclosure(L, LPCD::lua_StateFunctionDispatcher, nupvalues + 1); } template inline void lpcd_pushfunctorclosureex(lua_State* L, const Callee& callee, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) { unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(Callee*) + sizeof(func)); const void* pCallee = &callee; memcpy(buffer, &pCallee, sizeof(Callee*)); memcpy(buffer + sizeof(Callee*), &func, sizeof(func)); lua_insert(L, -1 - (int)nupvalues); lua_pushcclosure(L, LPCD::lua_StateMemberDispatcherHelper::lua_StateMemberDispatcher, nupvalues + 1); } /////////////////////////////////////////////////////////////////////////////// namespace LPCD { inline void* GetObjectUserdata(lua_State* L) { int type = lua_type(L, 1); if (type == LUA_TUSERDATA) return *(void **)(lua_touserdata(L, 1)); else if (type == LUA_TTABLE) { lua_pushstring(L, "__object"); lua_rawget(L, 1); void* ret; int subType = lua_type(L, -1); if (subType == LUA_TLIGHTUSERDATA) { ret = lua_touserdata(L, -1); } else if (subType == LUA_TUSERDATA) { ret = *(void **)(lua_touserdata(L, -1)); } else { ret = NULL; luaL_error(L, "The table does not have a userdata member called __object."); } lua_pop(L, 1); return ret; } else { luaL_argerror(L, 1, "must be userdata or a table with a userdata member called __object"); } return NULL; } inline void* GetInPlaceObjectUserdata(lua_State* L) { int type = lua_type(L, 1); if (type == LUA_TUSERDATA) return lua_touserdata(L, 1); else if (type == LUA_TTABLE) { lua_pushstring(L, "__object"); lua_rawget(L, 1); void* ret; int subType = lua_type(L, -1); if (subType == LUA_TLIGHTUSERDATA) { ret = lua_touserdata(L, -1); } else if (subType == LUA_TUSERDATA) { ret = lua_touserdata(L, -1); } else { ret = NULL; luaL_error(L, "The table does not have a userdata member called __object."); } lua_pop(L, 1); return ret; } else { luaL_argerror(L, 1, "must be userdata or a table with a userdata member called __object"); } return NULL; } template class Object_MemberDispatcherHelper { public: static inline int Object_MemberDispatcher(lua_State* L) { typedef int (Callee::*Functor)(lua_State*); unsigned char* buffer = GetFirstUpvalueAsUserdata(L); Functor& func = *(Functor*)(buffer); Callee& callee = *(Callee*)GetObjectUserdata(L); return (callee.*func)(L); } }; template class DirectCallObjectMemberDispatcherHelper { public: static inline int DirectCallMemberDispatcher(lua_State* L) { unsigned char* buffer = GetFirstUpvalueAsUserdata(L); Callee& callee = *(Callee*)GetObjectUserdata(L); return Call(callee, *(Func*)buffer, L, startIndex); } }; template class DirectCallInPlaceObjectMemberDispatcherHelper { public: static inline int DirectCallMemberDispatcher(lua_State* L) { unsigned char* buffer = GetFirstUpvalueAsUserdata(L); Callee& callee = *(Callee*)GetInPlaceObjectUserdata(L); return Call(callee, *(Func*)buffer, L, startIndex); } }; inline int PropertyMetatable_newindex(lua_State* L) { // table key value lua_pushvalue(L, 2); // table key value key lua_rawget(L, lua_upvalueindex(1)); // table key value property if (lua_isfunction(L, -1)) { if (lua_getupvalue(L, -1, 2)) { // table key value property userdataTest if (lua_touserdata(L, -1) == (void*)-2) { lua_pop(L, 1); // table key value property lua_CFunction f = lua_tocfunction(L, -1); // table key value propertyfunc lua_getupvalue(L, -1, 1); // table key value propertyfunc offset lua_replace(L, 4); // table key value offset return f(L); } lua_pop(L, 1); // table key value } lua_rawset(L, -3); // table return 0; } else if (!lua_isnil(L, -1)) { lua_pop(L, 1); // table key value lua_rawset(L, -3); // table return 0; } lua_pop(L, 1); // table key value if (!lua_getmetatable(L, -3)) // table key value metatable return 0; do { lua_getfield(L, -1, "__newindex"); // table key value metatable __newindex if (lua_isnil(L, -1)) { lua_pop(L, 2); // table key value lua_rawset(L, -3); // table return 0; } lua_getupvalue(L, -1, 1); // table key value metatable __newindex functions lua_pushvalue(L, 2); // table key value metatable __newindex functions key lua_rawget(L, -2); // table key value metatable __newindex functions property if (lua_isfunction(L, -1)) { if (lua_getupvalue(L, -1, 2)) { // table key value metatable __newindex functions userdataTest if (lua_touserdata(L, -1) == (void*)-2) { lua_pop(L, 1); // table key value metatable __newindex functions lua_CFunction f = lua_tocfunction(L, -1); // table key value metatable __newindex functions lua_getupvalue(L, -1, 1); // table key value metatable __newindex functions offset lua_replace(L, 4); // table key value offset __newindex functions return f(L); } lua_pop(L, 2); // table key value metatable __newindex } lua_rawset(L, -3); // table key value return 1; } else if (!lua_isnil(L, -1)) { lua_pop(L, 4); lua_rawset(L, -3); return 0; } lua_pop(L, 3); // table key value metatable if (!lua_getmetatable(L, 4)) { // table key value metatable metatable2 lua_pop(L, 1); break; } lua_remove(L, -2); // table key value metatable2 } while (true); lua_rawset(L, -3); return 0; } // function gettable_event (table, key) // upvalues: // 1 - function__index // 2 - properties__index inline int PropertyMetatable_index(lua_State* L) { lua_pushvalue(L, 2); // table key key lua_rawget(L, lua_upvalueindex(1)); // table key property if (lua_isfunction(L, -1)) { if (lua_getupvalue(L, -1, 2)) { if (lua_touserdata(L, -1) == (void*)-2) { lua_pop(L, 1); lua_CFunction f = lua_tocfunction(L, -1); // table key propertyfunc lua_getupvalue(L, -1, 1); // table key propertyfunc offset lua_replace(L, 3); // table key offset return f(L); } lua_pop(L, 1); } return 1; } else if (!lua_isnil(L, -1)) return 1; lua_pop(L, 1); // table key if (!lua_getmetatable(L, -2)) // table key metatable return 0; do { lua_getfield(L, -1, "__index"); // table key metatable __index if (lua_isnil(L, -1)) return 0; lua_getupvalue(L, -1, 1); // table key metatable __index functions lua_pushvalue(L, 2); // table key metatable __index functions key lua_rawget(L, -2); // table key metatable __index functions property if (lua_isfunction(L, -1)) { if (lua_getupvalue(L, -1, 2)) { // table key metatable __index functions userdataTest if (lua_touserdata(L, -1) == (void*)-2) { lua_pop(L, 1); // table key metatable __index functions lua_CFunction f = lua_tocfunction(L, -1); // table key metatable __index functions lua_getupvalue(L, -1, 1); // table key metatable __index functions offset lua_replace(L, 3); // table key offset __index functions return f(L); } lua_pop(L, 1); // table key metatable __index functions } return 1; } else if (!lua_isnil(L, -1)) return 1; lua_pop(L, 3); // table key metatable if (!lua_getmetatable(L, 3)) // table key metatable metatable2 return 0; lua_remove(L, -2); // table key metatable2 } while (true); } template class PropertyMemberHelper { public: static int PropertyGet(lua_State* L) { Object* obj = (Object*)LPCD::GetObjectUserdata(L); void* offset = lua_touserdata(L, 3); LPCD::Type::Push(L, *(VarType*)((unsigned char*)obj + (ptrdiff_t)offset)); return 1; } static int PropertySet(lua_State* L) { Object* obj = (Object*)LPCD::GetObjectUserdata(L); void* offset = lua_touserdata(L, 4); if (!LPCD::Type::Match(L, 3)) luaL_argerror(L, 3, "bad argument"); *(VarType*)((unsigned char*)obj + (ptrdiff_t)offset) = LPCD::Type::Get(L, 3); return 0; } }; template class InPlacePropertyMemberHelper { public: static int PropertyGet(lua_State* L) { Object* obj = (Object*)LPCD::GetInPlaceObjectUserdata(L); void* offset = lua_touserdata(L, 3); LPCD::Type::Push(L, *(VarType*)((unsigned char*)obj + (ptrdiff_t)offset)); return 1; } static int PropertySet(lua_State* L) { Object* obj = (Object*)LPCD::GetInPlaceObjectUserdata(L); void* offset = lua_touserdata(L, 4); if (!Type::Match(L, 3)) luaL_argerror(L, 3, "bad argument"); *(VarType*)((unsigned char*)obj + (ptrdiff_t)offset) = Type::Get(L, 3); return 0; } }; template class PropertyGlobalHelper { public: static int PropertyGet(lua_State* L) { void* offset = lua_touserdata(L, lua_upvalueindex(1)); LPCD::Type::Push(L, *(VarType*)offset); return 1; } static int PropertySet(lua_State* L) { void* offset = lua_touserdata(L, lua_upvalueindex(1)); if (!LPCD::Type::Match(L, 1)) luaL_argerror(L, 2, "bad argument"); *(VarType*)offset = LPCD::Type::Get(L, 1); return 1; } }; } // namespace LPCD template inline void lpcd_pushobjectfunctorclosure(lua_State* L, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) { unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func)); memcpy(buffer, &func, sizeof(func)); lua_pushcclosure(L, LPCD::Object_MemberDispatcherHelper::Object_MemberDispatcher, nupvalues + 1); } template inline void lpcd_pushobjectdirectclosure(lua_State* L, const Callee* callee, Func func, unsigned int nupvalues = 0) { unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func)); memcpy(buffer, &func, sizeof(func)); lua_pushcclosure(L, LPCD::DirectCallObjectMemberDispatcherHelper::DirectCallMemberDispatcher, nupvalues + 1); } template inline void lpcd_pushinplaceobjectfunctorclosure(lua_State* L, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) { unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func)); memcpy(buffer, &func, sizeof(func)); //lua_pushcclosure(L, LPCD::Object_InPlaceMemberDispatcherHelper::Object_MemberDispatcher, nupvalues + 1); } template inline void lpcd_pushinplaceobjectdirectclosure(lua_State* L, const Callee* callee, Func func, unsigned int nupvalues = 0) { unsigned char* buffer = (unsigned char*)lua_newuserdata(L, sizeof(func)); memcpy(buffer, &func, sizeof(func)); lua_pushcclosure(L, LPCD::DirectCallInPlaceObjectMemberDispatcherHelper::DirectCallMemberDispatcher, nupvalues + 1); } template inline void lpcd_pushmemberpropertygetclosure(lua_State* L, VarType Object::* var) { lua_pushlightuserdata(L, (void*)&(((Object*)0)->*var)); lua_pushlightuserdata(L, (void*)-2); lua_pushcclosure(L, &LPCD::PropertyMemberHelper::PropertyGet, 2); } template inline void lpcd_pushmemberpropertysetclosure(lua_State* L, VarType Object::* var) { lua_pushlightuserdata(L, (void*)&(((Object*)0)->*var)); lua_pushlightuserdata(L, (void*)-2); lua_pushcclosure(L, &LPCD::PropertyMemberHelper::PropertySet, 2); } template inline void lpcd_pushmemberinplacepropertygetclosure(lua_State* L, VarType Object::* var) { lua_pushlightuserdata(L, (void*)&(((Object*)0)->*var)); lua_pushlightuserdata(L, (void*)-2); lua_pushcclosure(L, &LPCD::InPlacePropertyMemberHelper::PropertyGet, 2); } template inline void lpcd_pushmemberinplacepropertysetclosure(lua_State* L, VarType Object::* var) { lua_pushlightuserdata(L, (void*)&(((Object*)0)->*var)); lua_pushlightuserdata(L, (void*)-2); lua_pushcclosure(L, &LPCD::InPlacePropertyMemberHelper::PropertySet, 2); } template inline void lpcd_pushglobalpropertygetclosure(lua_State* L, VarType* var) { lua_pushlightuserdata(L, (void*)var); lua_pushlightuserdata(L, (void*)-2); lua_pushcclosure(L, &LPCD::PropertyGlobalHelper::PropertyGet, 2); } template inline void lpcd_pushglobalpropertysetclosure(lua_State* L, VarType* var) { lua_pushlightuserdata(L, (void*)var); lua_pushlightuserdata(L, (void*)-2); lua_pushcclosure(L, &LPCD::PropertyGlobalHelper::PropertySet, 2); } /* convert a stack index to positive */ #define lpcd_abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1) inline void lpcd_integratepropertysupport(lua_State* L, int metatableIndex, bool inPlace = false) { metatableIndex = lpcd_abs_index(L, metatableIndex); lua_pushstring(L, "__index"); // metatable "__index" lua_newtable(L); // metatable "__index" __index lua_pushboolean(L, inPlace ? 1 : 0);// metatable "__index" __index inPlace lua_pushcclosure(L, LPCD::PropertyMetatable_index, 2); // metatable "__index" PropertyMetatable_index lua_rawset(L, metatableIndex); // metatable lua_pushstring(L, "__newindex"); // metatable "__newindex" lua_newtable(L); // metatable "__newindex" __newindex lua_pushboolean(L, inPlace ? 1 : 0);// metatable "__newindex" __newindex inPlace lua_pushcclosure(L, LPCD::PropertyMetatable_newindex, 2); // metatable "__newindex" PropertyMetatable_newindex lua_rawset(L, metatableIndex); // metatable } inline void lpcd_propertymetatable_getfunctions(lua_State* L, int metatableIndex) { lua_getfield(L, metatableIndex, "__index"); // (metatable) __index lua_getupvalue(L, -1, 1); // (metatable) __index props__functions lua_remove(L, -2); // (metatable) props__functions } inline void lpcd_newclassmetatable(lua_State* L, const char* className, const char* baseClassName, bool inPlace = false) { luaL_newmetatable(L, className); // class_metatable lpcd_integratepropertysupport(L, -1, inPlace); if (baseClassName) { luaL_getmetatable(L, baseClassName); // class_metatable baseClass_metatable lua_setmetatable(L, -2); // class_metatable } } template inline void lpcd_propertycreate(lua_State* L, int metatableIndex, const char* varName, VarType Object::* var, bool read = true, bool write = true) { lua_pushvalue(L, metatableIndex); // metatable lua_pushstring(L, varName); // metatable varName if (read) { lua_getfield(L, -2, "__index"); // metatable varName __index lua_getupvalue(L, -1, 1); // metatable varName __index functions lua_getupvalue(L, -2, 2); // metatable varName __index functions inPlace bool inPlace = lua_toboolean(L, -1) != 0; lua_pop(L, 1); // metatable varName __index functions lua_pushvalue(L, -3); // metatable varName __index functions varName inPlace ? lpcd_pushmemberinplacepropertygetclosure(L, var) : lpcd_pushmemberpropertygetclosure(L, var); // metatable varName __index functions varName closure lua_rawset(L, -3); // metatable varName __index functions lua_pop(L, 2); // metatable varName } if (write) { lua_getfield(L, -2, "__newindex"); // metatable varName __newindex lua_getupvalue(L, -1, 1); // metatable varName __newindex functions lua_getupvalue(L, -2, 2); // metatable varName __newindex functions inPlace bool inPlace = lua_toboolean(L, -1) != 0; lua_pop(L, 1); // metatable varName __newindex functions lua_pushvalue(L, -3); // metatable varName __newindex functions varName inPlace ? lpcd_pushmemberinplacepropertysetclosure(L, var) : lpcd_pushmemberpropertysetclosure(L, var); // metatable varName __newindex functions varName closure lua_rawset(L, -3); // metatable varName __newindex functions lua_pop(L, 2); // metatable varName } lua_pop(L, 2); } inline void* lpcd_checkobject(lua_State* L, int index, const char* tname, bool throwError = true) { assert(tname); int type = lua_type(L, index); if (type == LUA_TTABLE) { lua_getfield(L, index, "__object"); if (lua_getmetatable(L, -1)) { /* does it have a metatable? */ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ int equal = lua_rawequal(L, -1, -2); /* does it have the correct mt? */ lua_pop(L, 2); /* remove both metatables */ if (!equal) { lua_pop(L, 1); goto error; } } void *p = lua_touserdata(L, -1); lua_pop(L, 1); return p; } else if (type == LUA_TUSERDATA) { if (lua_getmetatable(L, index)) { /* does it have a metatable? */ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ int equal = lua_rawequal(L, -1, -2); /* does it have the correct mt? */ lua_pop(L, 2); /* remove both metatables */ if (!equal) goto error; } return lua_touserdata(L, index); } error: if (throwError) { const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, luaL_typename(L, index)); luaL_argerror(L, index, msg); } return NULL; } namespace LPCD { class Class { public: Class(lua_State* L, const char* className, const char* baseClassName = NULL) : L(L) { lpcd_newclassmetatable(L, className, baseClassName); lpcd_propertymetatable_getfunctions(L, -1); } ~Class() { lua_pop(L, 2); } void MetatableFunction(const char* name, lua_CFunction func, unsigned int nupvalues = 0) { lua_pushcclosure(L, func, nupvalues); lua_setfield(L, -3, name); } template Class& Property(const char* varName, VarType Object::* var, bool read = true, bool write = true) { lpcd_propertycreate(L, -2, varName, var, read, write); return *this; } void Function(const char* name, lua_CFunction func, unsigned int nupvalues = 0) { lua_pushcclosure(L, func, nupvalues); lua_setfield(L, -2, name); } template inline Class& ObjectFunctor(const char* name, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) { lpcd_pushobjectfunctorclosure(L, func, nupvalues); lua_setfield(L, -2, name); return *this; } template inline Class& ObjectDirect(const char* name, const Callee* callee, Func func, unsigned int nupvalues = 0) { lpcd_pushobjectdirectclosure(L, callee, func, nupvalues); lua_setfield(L, -2, name); return *this; } lua_State* L; }; class InPlaceClass { public: InPlaceClass(lua_State* L, const char* className, const char* baseClassName = NULL) : L(L) { lpcd_newclassmetatable(L, className, baseClassName, true); lpcd_propertymetatable_getfunctions(L, -1); } ~InPlaceClass() { lua_pop(L, 2); } void MetatableFunction(const char* name, lua_CFunction func, unsigned int nupvalues = 0) { lua_pushcclosure(L, func, nupvalues); lua_setfield(L, -3, name); } template InPlaceClass& Property(const char* varName, VarType Object::* var, bool read = true, bool write = true) { lpcd_propertycreate(L, -2, varName, var, read, write); return *this; } template inline InPlaceClass& ObjectFunctor(const char* name, int (Callee::*func)(lua_State*), unsigned int nupvalues = 0) { lpcd_pushinplaceobjectfunctorclosure(L, func, nupvalues); lua_setfield(L, -2, name); return *this; } template inline InPlaceClass& ObjectDirect(const char* name, const Callee* callee, Func func, unsigned int nupvalues = 0) { lpcd_pushinplaceobjectdirectclosure(L, callee, func, nupvalues); lua_setfield(L, -2, name); return *this; } lua_State* L; }; } // namespace LPCD #endif // LUAPLUS__LUAPLUSCD_H