【发布时间】:2012-06-26 00:35:12
【问题描述】:
我正在尝试将 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
...
我的 Push 函数基本上应该检查某处是否已经存在相同的 C++ 类指针,如果是,则推送相关的 userdata 指针(无论我如何推送它,对象应该以 1:1 相同的方式工作)
如果不是,它应该创建一个新的用户数据(将其压入堆栈)并将其内容设置为类对象。
这是我的代码:
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;
}
【问题讨论】:
-
我发现很难准确地确定您在这里尝试做什么。您是否只是在创建 lua 用户数据实例后尝试缓存它?
-
我正在尝试推送 userdata 值,同时仍然可以在它们上使用 '=='、'~=' 等,因此如果它是相同的 C++ 对象,则 userdata 指针必须相同.
-
Lua 用户数据对象在内部通过引用进行比较。从同一个底层指针创建的两个 userdata 实例应该比较相等。你是说
==在这种情况下不起作用吗?您是否覆盖了__eq元表条目? -
在这种情况下,'==' 检查失败。不,我没有覆盖 __eq...
-
它是否真的比较用户数据内容本身并检查它是否相等?
标签: c++ class lua lua-userdata