Allow binding methods in Lua classes
This commit is contained in:
parent
70fdf31ad0
commit
c6c640bdbc
1 changed files with 62 additions and 2 deletions
|
@ -69,6 +69,11 @@ private:
|
||||||
lua_obj_pin& operator=(const lua_obj_pin&);
|
lua_obj_pin& operator=(const lua_obj_pin&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class T> struct lua_class_bind_data
|
||||||
|
{
|
||||||
|
int (T::*fn)(lua_State* LS);
|
||||||
|
};
|
||||||
|
|
||||||
template<class T> class lua_class;
|
template<class T> class lua_class;
|
||||||
|
|
||||||
template<class T> lua_class<T>& objclass();
|
template<class T> lua_class<T>& objclass();
|
||||||
|
@ -102,6 +107,7 @@ public:
|
||||||
lua_pushvalue(LS, -3);
|
lua_pushvalue(LS, -3);
|
||||||
lua_pushvalue(LS, -3);
|
lua_pushvalue(LS, -3);
|
||||||
lua_rawset(LS, -3);
|
lua_rawset(LS, -3);
|
||||||
|
lua_pop(LS, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(lua_State* LS, const char* keyname)
|
void bind(lua_State* LS, const char* keyname)
|
||||||
|
@ -110,6 +116,36 @@ public:
|
||||||
lua_pushstring(LS, keyname);
|
lua_pushstring(LS, keyname);
|
||||||
lua_pushvalue(LS, -3);
|
lua_pushvalue(LS, -3);
|
||||||
lua_rawset(LS, -3);
|
lua_rawset(LS, -3);
|
||||||
|
lua_pop(LS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int class_bind_trampoline(lua_State* LS)
|
||||||
|
{
|
||||||
|
lua_class_bind_data<T>* b = (lua_class_bind_data<T>*)lua_touserdata(LS, lua_upvalueindex(1));
|
||||||
|
const char* fname = lua_tostring(LS, lua_upvalueindex(2));
|
||||||
|
T* p = lua_class<T>::get(LS, 1, fname);
|
||||||
|
return (p->*(b->fn))(LS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind(lua_State* LS, const char* keyname, int (T::*fn)(lua_State* LS))
|
||||||
|
{
|
||||||
|
load_metatable(LS);
|
||||||
|
lua_pushstring(LS, keyname);
|
||||||
|
lua_rawget(LS, -2);
|
||||||
|
if(!lua_isnil(LS, -1)) {
|
||||||
|
lua_pop(LS, 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lua_pop(LS, 1);
|
||||||
|
lua_class_bind_data<T>* bdata = new lua_class_bind_data<T>;
|
||||||
|
bdata->fn = fn;
|
||||||
|
lua_pushstring(LS, keyname);
|
||||||
|
lua_pushlightuserdata(LS, bdata);
|
||||||
|
std::string name = std::string("Method ") + keyname;
|
||||||
|
lua_pushstring(LS, name.c_str());
|
||||||
|
lua_pushcclosure(LS, class_bind_trampoline, 2);
|
||||||
|
lua_rawset(LS, -3);
|
||||||
|
lua_pop(LS, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
T* _get(lua_State* LS, int arg, const char* fname, bool optional = false)
|
T* _get(lua_State* LS, int arg, const char* fname, bool optional = false)
|
||||||
|
@ -121,10 +157,12 @@ public:
|
||||||
goto badtype;
|
goto badtype;
|
||||||
}
|
}
|
||||||
load_metatable(LS);
|
load_metatable(LS);
|
||||||
if(!lua_getmetatable(LS, arg))
|
if(!lua_getmetatable(LS, arg)) {
|
||||||
goto badtype;
|
goto badtype;
|
||||||
if(!lua_rawequal(LS, -1, -2))
|
}
|
||||||
|
if(!lua_rawequal(LS, -1, -2)) {
|
||||||
goto badtype;
|
goto badtype;
|
||||||
|
}
|
||||||
lua_pop(LS, 2);
|
lua_pop(LS, 2);
|
||||||
return reinterpret_cast<T*>(lua_touserdata(LS, arg));
|
return reinterpret_cast<T*>(lua_touserdata(LS, arg));
|
||||||
badtype:
|
badtype:
|
||||||
|
@ -176,6 +214,20 @@ private:
|
||||||
obj->~T();
|
obj->~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int newindex(lua_State* LS)
|
||||||
|
{
|
||||||
|
lua_pushstring(LS, "Writing metatables of classes is not allowed");
|
||||||
|
lua_error(LS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int index(lua_State* LS)
|
||||||
|
{
|
||||||
|
lua_getmetatable(LS, 1);
|
||||||
|
lua_pushvalue(LS, 2);
|
||||||
|
lua_rawget(LS, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void load_metatable(lua_State* LS)
|
void load_metatable(lua_State* LS)
|
||||||
{
|
{
|
||||||
again:
|
again:
|
||||||
|
@ -185,9 +237,17 @@ again:
|
||||||
lua_pop(LS, 1);
|
lua_pop(LS, 1);
|
||||||
lua_pushlightuserdata(LS, this);
|
lua_pushlightuserdata(LS, this);
|
||||||
lua_newtable(LS);
|
lua_newtable(LS);
|
||||||
|
lua_pushvalue(LS, -1);
|
||||||
|
lua_setmetatable(LS, -2);
|
||||||
lua_pushstring(LS, "__gc");
|
lua_pushstring(LS, "__gc");
|
||||||
lua_pushcfunction(LS, &lua_class<T>::dogc);
|
lua_pushcfunction(LS, &lua_class<T>::dogc);
|
||||||
lua_rawset(LS, -3);
|
lua_rawset(LS, -3);
|
||||||
|
lua_pushstring(LS, "__newindex");
|
||||||
|
lua_pushcfunction(LS, &lua_class<T>::newindex);
|
||||||
|
lua_rawset(LS, -3);
|
||||||
|
lua_pushstring(LS, "__index");
|
||||||
|
lua_pushcfunction(LS, &lua_class<T>::index);
|
||||||
|
lua_rawset(LS, -3);
|
||||||
lua_rawset(LS, LUA_REGISTRYINDEX);
|
lua_rawset(LS, LUA_REGISTRYINDEX);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue