+-
c – Lua userdata指针的生命周期
如果我创建一个userdata对象并将其存储在一个表中,那么在C/C++中获取它的引用,该引用有效多长时间?只要用户数据保存在Lua的表中,C/C++中的引用是否保证有效?或者是否存在Lua运行时移动userdata对象的风险,使C/C++引用无效?

这是我正在做的事情:

// Initially, the stack contains a table
class Foo { ... };
lua_pushstring(L, "my_userdata");
void* mem = lua_newuserdata(L, sizeof(Foo));
new (mem) Foo();
lua_settable(L, -3);

// Later:
lua_pushstring(L, "my_userdata");
lua_gettable(L, -2);
Foo *foo = (Foo*)lua_touserdata(L, -1);
lua_pop(L, 1);
// How long will this pointer be valid?

我最好在这里使用operator new和light userdata吗?

最佳答案
引用(或Lua以C语言编写的指针)将在userdata的生命周期内保持有效.

Lua的首席架构师在Lua-l mailing list上解决了这个问题:

Quote: Apr 18, 2006; Roberto Ierusalimschy

The caution is about strings, not about userdata (although we actually
did not say that explicitly in the manual). We have no intention of
allowing userdata addresses to change during GC. Unlike strings, which
are an internal data in Lua, the only purpose of userdata is to be used
by C code, which prefer that things stay where they are 🙂

您可以通过将其锚定在以下状态来控制用户数据的生命周期:

>在registry年
>作为uservalue与另一个物体的生命联系在一起
>作为全局存储在pseudo-index LUA_RIDX_GLOBALS的表中

有几个原因你可能比lightuserdata更喜欢完整的用户数据:

>完整的userdata可能有自己的uservalue和metatable(所有lightuserdata共享相同的metatable)
>通过__gc元方法完成
>用于处理userdata的几个便利API函数(luaL_newmetatable,luaL_setmetatable等)

从C中的类创建userdata的常用方法是使用pointer-to-pointer idiom:

class Foo { ... };

static int new_Foo(lua_State *L) {
    // begin userdata lifetime
    Foo **ud = static_cast<Foo **>(lua_newuserdata(L, sizeof *ud)); 
    luaL_setmetatable(L, "Foo");

    // begin C++ object lifetime  
    *ud = new Foo();
    return 1;
}

// __gc metamethod
static int delete_Foo(lua_State *L) {  
    Foo **ud = static_cast<Foo **>(luaL_checkudata(L, 1, "Foo"));

    // end C++ object lifetime
    delete *ud;

    // end userdata lifetime
    return 0;
}
点击查看更多相关文章

转载注明原文:c – Lua userdata指针的生命周期 - 乐贴网