renyson
renyson

Reputation: 21

Lua life cycle of userdata and uservalue

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

Answers (0)

Related Questions