如果我创建一个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
和轻量级用户数据吗?
答案 0 :(得分:3)
引用(或者由于Lua是用C语言编写的指针)将在userdata的生命周期内保持有效。
Lua的首席架构师在Lua-l mailing list上发表了这篇文章:
引用:2006年4月18日; Roberto Ierusalimschy
谨慎是关于字符串,而不是关于userdata(尽管我们实际上是这样) 没有在手册中明确说明)。我们无意 允许用户数据地址在GC期间更改。与字符串不同 是Lua中的内部数据,用户数据的唯一目的就是使用它 通过C代码,它希望事物保持原样:)
您可以通过将用户数据锚定在以下状态来控制用户数据的生命周期:
LUA_RIDX_GLOBALS
有几个原因可能比lightuserdata更喜欢完整的用户数据:
__gc
元方法在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;
}
答案 1 :(得分:2)
在Lua垃圾收集器确定表(或表元素)不再在任何地方使用并且可以安全删除之前一直有效。使用metamethod,Lua会在垃圾收集发生时通知你。