Lua userdata 和 uservalue 的生命周期

我在 Lua 5.3 中创建了一个 userdata 并设置它的 uservalue(一个 table 值)。当我使用 collectgarbage() 函数是,uservalue 被回收,但是 userdata 没有被回收。

为什么 userdata 和 uservalue 的生命周期不同?我怎样才能让 uservalue 不被回收?

我的代码:

setpeer 是设置 uservalue 的函数(uservalue 始终是一个 lua table),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 是 c# 对象(userdata),index 是一个 lua table(类似于一个类)。

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_

然后我使用这个 userdata,item 是一个 userdata(c#对象),update 是 lua table 中的一个函数。当我执行 collectgarbage() 时,update 变成了 nil 并且 getpeer 也返回了 nil,因此我认为 uservalue 已经被回收。(如果不执行 collectgarbage() 就不会被回收)

    item:update(dataArr[index+1])

原文链接 https://stackoverflow.com/questions/69806136

点赞