2

我在 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])
4

0 回答 0