Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用户数据对象管理_C++_Class_Lua_Lua Userdata - Fatal编程技术网

C++ 用户数据对象管理

C++ 用户数据对象管理,c++,class,lua,lua-userdata,C++,Class,Lua,Lua Userdata,我试图将Lua类对象推送到堆栈上。指向该对象的指针可以由多个函数返回 换句话说,我需要在UpRADIUS数据值的同时保持使用“=”、“~=”等的能力,因此USER数据指针必须是相同的,如果它是同一个C++对象。 -- this should push the object onto the stack local firstObject = GetClassObject(); firstObject:doSomething(); firstObject将由lua脚本存储,稍后在代码中,我需要再

我试图将Lua类对象推送到堆栈上。指向该对象的指针可以由多个函数返回

换句话说,我需要在UpRADIUS数据值的同时保持使用“=”、“~=”等的能力,因此USER数据指针必须是相同的,如果它是同一个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++类指针在某处并推导出关联的用户数据指针,如果是这样(不管我如何推它,对象应该工作1:1)

如果没有,它应该创建一个新的userdata(将其推到堆栈上),并将其内容设置为class对象

这是我的密码:

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;
}

对,在Lua中,相同userdata的任意两个实例都保证相等。然而,当你正在练习一个C++类实例时,每个装箱实例都被放入一个新的用户数据表,这意味着它们不能直接比较。 您需要做的是为您的对象定义一个
\uu eq
元方法。它可能看起来有点像这样:

int l_compare_things(lua_State* l)
{
    MyClass* a = reinterpret_cast<MyClass*>(lua_touserdata(L, 1));
    MyClass* b = reinterpret_cast<MyClass*>(lua_touserdata(L, 2));

    lua_pushboolean(L, (*a) == (*b));

    return 1;
}
(注意:我没有编译或测试这个示例。E&OE!)


这将使与某个特定的
MyClass
实例关联的userdatum留在堆栈顶部。您需要采取自己的步骤来“注销”类实例;在这种情况下,注册表中存在对每个实例的硬引用,因此在销毁该引用之前,不会对userdatum进行垃圾收集。您可以考虑使用弱/星历表。

< P>右,在Lua中,相同用户数据的任何两个实例都保证相等。然而,当你正在练习一个C++类实例时,每个装箱实例都被放入一个新的用户数据表,这意味着它们不能直接比较。 您需要做的是为您的对象定义一个
\uu eq
元方法。它可能看起来有点像这样:

int l_compare_things(lua_State* l)
{
    MyClass* a = reinterpret_cast<MyClass*>(lua_touserdata(L, 1));
    MyClass* b = reinterpret_cast<MyClass*>(lua_touserdata(L, 2));

    lua_pushboolean(L, (*a) == (*b));

    return 1;
}
(注意:我没有编译或测试这个示例。E&OE!)


这将使与某个特定的
MyClass
实例关联的userdatum留在堆栈顶部。您需要采取自己的步骤来“注销”类实例;在这种情况下,注册表中存在对每个实例的硬引用,因此在销毁该引用之前,不会对userdatum进行垃圾收集。您可以考虑使用弱/星历表。

< P>这是弱表是如何工作的?

void Push( const T &tObject )
{
    std::ostringstream o;
    o << tObject;
    std::string sIdentifier = o.str();
    const char *pszIdentifier = sIdentifier.c_str();

    lua_State *L = GetLuaState();
    luaL_getmetatable( L, "lua_userdata" );
    if( !lua_istable( L, -1 ) )
    {
        // create new weak table
        luaL_newmetatable( L, "lua_userdata" );
        lua_pushstring( L, "v" );
        lua_setfield( L, -2, "__mode" );
    }

    lua_getfield( L, -1, pszIdentifier );
    if( lua_isuserdata( L, -1 ) == TRUE )
        return lua_remove( L, -2 );

    lua_pop( L, 1 ); // didnt exist yet - getfield is nil -> need to pop that
    void *pUserData = lua_newuserdata( L, sizeof( UINT64 ) );
    *reinterpret_cast<UINT64*>( pUserData ) = UINT64( tObject );

    lua_pushvalue( L, -1 );
    lua_setfield( L, -3, pszIdentifier );
    lua_remove( L, -2 );
}
void Push(const T&tObject)
{
std::ostringstream o;
你需要把它打开
void*pUserData=lua_newuserdata(L,sizeof(UINT64));
*重新解释铸造(pUserData)=UINT64(tObject);
lua_值(L,-1);
lua_设置域(L,-3,pszIdentifier);
lua_移除(L,-2);
}

弱表就是这样工作的吗

void Push( const T &tObject )
{
    std::ostringstream o;
    o << tObject;
    std::string sIdentifier = o.str();
    const char *pszIdentifier = sIdentifier.c_str();

    lua_State *L = GetLuaState();
    luaL_getmetatable( L, "lua_userdata" );
    if( !lua_istable( L, -1 ) )
    {
        // create new weak table
        luaL_newmetatable( L, "lua_userdata" );
        lua_pushstring( L, "v" );
        lua_setfield( L, -2, "__mode" );
    }

    lua_getfield( L, -1, pszIdentifier );
    if( lua_isuserdata( L, -1 ) == TRUE )
        return lua_remove( L, -2 );

    lua_pop( L, 1 ); // didnt exist yet - getfield is nil -> need to pop that
    void *pUserData = lua_newuserdata( L, sizeof( UINT64 ) );
    *reinterpret_cast<UINT64*>( pUserData ) = UINT64( tObject );

    lua_pushvalue( L, -1 );
    lua_setfield( L, -3, pszIdentifier );
    lua_remove( L, -2 );
}
void Push(const T&tObject)
{
std::ostringstream o;
你需要把它打开
void*pUserData=lua_newuserdata(L,sizeof(UINT64));
*重新解释铸造(pUserData)=UINT64(tObject);
lua_值(L,-1);
lua_设置域(L,-3,pszIdentifier);
lua_移除(L,-2);
}


我发现很难准确了解您在这里想要做什么。在创建了LUAUSEDATA实例之后,是否只是试图缓存一个LUAUSEDATA实例?我试图在使用USER数据值的同时保持它们的“使用=”、“~=”等的能力,因此USER数据指针必须是相同的,如果它是同一C++对象。LUA USEDATA对象通过内部引用进行比较。从同一基础指针创建的两个userdata实例应进行相等的比较。你是说在这种情况下,
==
不起作用吗?您是否覆盖了
\uu eq
元表条目?在这种情况下,'=='检查失败。不,我没有覆盖uuueq…它是否真的比较userdatas内容本身并检查其是否相等?我发现很难准确地计算出您在这里要做什么。在创建了LUAUSEDATA实例之后,是否只是试图缓存一个LUAUSEDATA实例?我试图在使用USER数据值的同时保持它们的“使用=”、“~=”等的能力,因此USER数据指针必须是相同的,如果它是同一C++对象。LUA USEDATA对象通过内部引用进行比较。从同一基础指针创建的两个userdata实例应进行相等的比较。你是说在这种情况下,
==
不起作用吗?您是否覆盖了
\uu eq
元表条目?在这种情况下,'=='检查失败。不,我没有重写uu eq…它是否真的比较userdatas内容本身并检查其是否相等?为此,很遗憾,我不知道弱/短命表是如何工作的。它们做了什么?我尝试将所有userdata及其值映射到std::map中,并添加了自己的
\uu gc
方法,但没有起作用。我将完整的userdata指针按为light userdata,dsn不起作用:c@user1478081一步一个脚印。在基本推送系统正常工作之前,不要担心弱表!我不确定你想用你的
std::map
完成什么;你能使用我上面的代码吗?是的,一切正常,但正如你所说的,它会导致内存泄漏。看看下面我是如何修复的:)@user1478081:这至少是个好消息!您使用的是哪个版本的lua?谢谢,很遗憾,我不知道弱/短命表是如何工作的。它们做了什么?我尝试将所有用户数据及其值映射到一个std::map中,并添加了自己的
\u gc
方法,但没有起作用。我将完整的userdata指针按为light userdata,dsn不起作用:c@user1478081一步一个脚印。在基本推送系统正常工作之前,不要担心弱表!我不确定你想用你的
std::map
完成什么;你能使用我上面的代码吗?是的,一切都正常,但它会导致内存泄漏