// push onto the Lua stack a userdata containing a pointer to T object static int push(lua_State *L, T *obj, bool gc=false) { if (!obj) { lua_pushnil(L); return 0; } luaL_getmetatable(L, ("Lunar_" + std::string(T::className)).c_str()); // lookup metatable in Lua registry if (lua_isnil(L, -1)) luaL_error(L, "%s missing metatable", T::className); int mt = lua_gettop(L); subtable(L, mt, "userdata", "v"); userdataType *ud = static_cast<userdataType*>(pushuserdata(L, obj, sizeof(userdataType))); if (ud) { ud->pT = obj; // store pointer to object in userdata lua_pushvalue(L, mt); lua_setmetatable(L, -2); if (gc == false) { lua_checkstack(L, 3); subtable(L, mt, "do not trash", "k"); lua_pushvalue(L, -2); lua_pushboolean(L, 1); lua_settable(L, -3); lua_pop(L, 1); } } lua_replace(L, mt); lua_settop(L, mt); return mt; // index of userdata containing pointer to T object }
// push onto the Lua stack a userdata containing a pointer to T object static int push(lua_State *L, T *obj, bool gc = false) { if (obj == nullptr) { return 0; } luaL_getmetatable(L, T::className); // [-0,+1,-] if (lua_isnil(L, -1)) { return luaL_error(L, "'%s' missing metatable", T::className); } int l_mt = lua_gettop(L); /* Was this pointer pushed already? Then pushuserdata pushed the existing copy */ if (!pushuserdata(L, obj)) { return 1; } int l_ud = lua_gettop(L); lua_pushvalue(L, l_mt); // dup(mt) lua_setmetatable(L, l_ud); // mt(ud)=mt [-1,+0,-] if (!gc) { subtable(L, l_mt, "do not trash", "k"); lua_pushvalue(L, l_ud); lua_pushboolean(L, true); lua_rawset(L, -3); } lua_settop(L, l_ud); lua_replace(L, l_mt); int nresult = LunarWrapper::prep(obj, L); if (nresult != 0) { const char *msg = nullptr; int err = lua_gettop(L); if (err >= 0) { msg = lua_tostring(L, err); } if (msg == nullptr) { msg = "(unknown error)"; } return luaL_error(L, "'%s' failed to prepare: %s", T::className, msg); } return 1; }