Reputation: 21
I am creating userdata on Lua 5.3 and setting its uservalue (a table value). When I use collectgarbage()
the uservalue is collected, however the userdata is not.
Why is the life cycle of userdata and uservalue different? How can I make the uservalue not be collected?
My code:
setpeer is a function to set uservalue(always is a lua table), getpeer is a function to get uservalue
LUA_API int setpeer(lua_State* L) {
/* stack: userdata, table */
if (!lua_isuserdata(L, -2)) {
lua_pushstring(L, "Invalid argument #1 to setpeer: userdata expected.");
lua_error(L);
};
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushvalue(L, XLUA_NOPEER);
};
lua_setuservalue(L, -2);
return 0;};
LUA_API int getpeer(lua_State* L) {
/* stack: userdata */
if (!lua_isuserdata(L, -1)) {
print_str(L, "gy in getpeer is userdata");
lua_pushstring(L, "Invalid argument #1 to setpeer: userdata expected.");
lua_error(L);
};
print_str(L, "gy in Getpeer, it is a userdata!");
lua_getuservalue(L, -1);
if (lua_rawequal(L, -1, XLUA_NOPEER)) {
lua_pop(L, 1);
lua_pushnil(L);
};
return 1;};
use setpeer in lua file, t is a c# object(userdata), and index is a lua table(like a class)
local setmetatableindex_
setmetatableindex_ = function(t, index)
if type(t) == "userdata" then
local peer = xlua.getpeer(t)
if not peer then
peer = {}
xlua.setpeer(t, peer)
end
--local mt = getmetatable(t)
--if not mt then mt = {} end
--if not mt.__index then
-- mt.__index = peer
-- setmetatable(t, mt)
--end
setmetatableindex_(peer, index)
else
local mt = getmetatable(t)
if not mt then mt = {} end
if not mt.__index then
mt.__index = index
setmetatable(t, mt)
elseif mt.__index ~= index then
setmetatableindex_(mt, index)
end
end
end
setmetatableindex = setmetatableindex_
then, I use this userdata, item is a userdata(c# object), update is a funtion in lua table. when I do collectgarbage(), update will be nil and getpeer return nil too, so I think uservalue has been gc-ed.(if not collectgarbage(), won't)
item:update(dataArr[index+1])
Upvotes: 2
Views: 348