Esempio n. 1
0
 // 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;
	}