Я пытаюсь вставить объект класса Lua в стек. Указатель на этот объект может быть возвращен несколькими функциями.Lua userdata управление объектами
Другими словами: мне нужно указывать значения пользовательских данных, сохраняя при этом возможность использовать '==', '~ =' и т. Д., Поэтому указатель userdata должен быть тем же самым, если это тот же объект C++.
-- this should push the object onto the stack
local firstObject = GetClassObject();
firstObject:doSomething();
firstObject будет храниться скриптом Lua, а затем в коде мне нужно будет делать это снова:
-- the c++ class pointer has not changed here
-- so I would like to push the same userdata pointer as in the first call...
local object = GetClassObject();
-- if I would not do this the following here would fail... :C
if object == firstObject then
...
Моя функция Нажмите в основном должна проверить, есть ли уже указатель класса же C++ где-то и нажимайте соответствующий указатель userdata, если это так (независимо от того, как я его нажимаю, объект должен работать 1: 1 то же самое)
Если нет, он должен создать новую userdata (нажать на нее в стеке) и установить содержимое это объект класса.
Вот мой код:
template <typename T>
void Push(const T &tObject)
{
lua_State *L = GetLuaState();
// Here i need to check if such a C++ object (the same tObject)
// already exists!
//
// If so i want to push the associated userdata.
// Object didn't exist yet -> we need a new userdata
void *pUserData = lua_newuserdata(L, sizeof(tObject));
*reinterpret_cast<T*>(pUserData) = tObject;
}
template <typename T>
void Push(const T &tObject, const char *pszTable)
{
Push(tObject);
lua_State *L = GetLuaState();
luaL_getmetatable(L, pszTable);
lua_setmetatable(L, -2);
}
template <typename T>
T& Get(int nIndex)
{
T *pUserData = reinterpret_cast<T*>(lua_touserdata(GetLuaState(), nIndex));
if(pUserData == nullptr)
throw std::exception("Invalid userdata!");
return *pUserData;
}
template <typename T>
T& Get(int nIndex, const char *pszTable)
{
T *pUserData = reinterpret_cast<T*>(LuaToUData(nIndex, pszTable));
if(pUserData == nullptr)
throw std::exception("Invalid userdata!");
return *pUserData;
}
LuaToUData является собственной функцией, которую я написал, чтобы не бросить ошибку Lua:
void* LuaToUData(int nIndex, const char *pszTable)
{
void *pUserData = lua_touserdata(g_luaState, nIndex);
if(pUserData != nullptr)
{
if(lua_getmetatable(g_luaState, nIndex) != 0)
{
lua_getfield(g_luaState, LUA_REGISTRYINDEX, pszTable);
bool bEqual = (lua_rawequal(g_luaState, -1, -2) == 1);
lua_pop(g_luaState, 2);
if(bEqual)
return pUserData;
}
}
return nullptr;
}
Мне сложно определить, что вы пытаетесь сделать здесь. Вы просто пытаетесь кэшировать экземпляр userua lua после его создания? – Rook
Я пытаюсь использовать значения userdata, сохраняя при этом возможность использовать '==', '~ =' и т. Д., Поэтому указатель userdata должен быть тем же самым, если это тот же объект C++. – user1478081
Объекты User Lata Lua сравниваются по ссылке внутри. Два экземпляра userdata, созданные из одного и того же базового указателя, должны сравниваться как равные. Вы говорите, что '==' не работает в этом случае? И переопределили ли вы мета-запись '__eq'? – Rook