我在 Lua 5.3 上创建 userdata 并设置它的 uservalue (a table value)。当我使用collectgarbage()
uservalue 被收集,但是 userdata 不是。
为什么userdata和uservalue的生命周期不同?如何使用户价值不被收集?
我的代码:
setpeer 是一个设置 uservalue 的函数(总是一个 lua 表),getpeer 是一个获取 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;};
在 lua 文件中使用 setpeer,t 是 ac# object(userdata),index 是一个 lua 表(就像一个类)
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_
然后,我使用这个用户数据,项目是用户数据(c# 对象),更新是 lua 表中的一个函数。当我执行 collectgarbage() 时,更新将为 nil,getpeer 也返回 nil,所以我认为 uservalue 已被 gc-ed。(如果不是 collectgarbage(),则不会)
item:update(dataArr[index+1])