Reputation: 7951
If I create a userdata object and stash it in a table, then get a reference to it in C/C++, for how long is that reference valid? Is the reference in C/C++ guaranteed to be valid for as long as the userdata is held in the table in Lua? Or is there a risk that the Lua runtime will move the userdata object, invalidating the C/C++ reference to it?
Here's what I'm doing:
// 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?
Am I better off using operator new
and a light userdata here?
Upvotes: 4
Views: 1593
Reputation: 3103
The reference (or pointer since Lua is written in C) will remain valid for the lifetime of the userdata.
Lua's chief architect addressed this on the 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 :)
You can control the lifetime of a userdata by anchoring it in the state:
LUA_RIDX_GLOBALS
There are several reasons you may prefer a full userdata over a lightuserdata:
__gc
metamethodA common way of creating userdata from a class in C++ is to use the 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;
}
Upvotes: 4
Reputation: 1869
It is valid until the Lua garbage collector determines that the table (or table element) is no longer in use anywhere and can be safely deleted. Using metamethod, Lua will notify you when the garbage collection occurs.
http://pgl.yoyo.org/luai/i/lua_newuserdata
https://www.lua.org/pil/29.html
Upvotes: 3