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?
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With