将一个userdata元表添加到Lua表中

我使用userdata对象成功运作的脚本系统。但是,我现在想在我的userdata上有一个可以拿一个正常的表的属性。

我想我应该创建一个常规表,并设置metatable使用我的当前一组元方法,但我很难理解如何做到这一点 - 我肯定这是一个简单的调整,我现在看不到它。

我的现有代码看起来像:

void
LuaContext::push(lua_State* state, boost::shared_ptr<LuaWrapped> wrapped) {
    static struct luaL_Reg methods[] = {
        { "__index", LuaWrapped::static_get },
        { "__newindex", LuaWrapped::static_set },
        { "__len", LuaWrapped::static_len },
        { "__ipairs", LuaWrapped::static_ipairs },
        { "__pairs", LuaWrapped::static_pairs },
        { "__gc", LuaWrapped::static_gc },
        { "__eq", LuaWrapped::static_eq },
        { NULL, NULL }
    };

    LuaWrapped::Ptr **ptr = (LuaWrapped::Ptr **)lua_newuserdata(state, sizeof(LuaWrapped::Ptr *));
    *ptr = new LuaWrapped::Ptr(wrapped);

    if (luaL_newmetatable(state, "LuaWrapped")) {
        lua_pushstring(state, "__index");
        lua_pushvalue(state, -2);
        lua_settable(state, -3);
        luaL_openlib(state, NULL, methods, 0);
    }
    lua_setmetatable(state, -2);
}

__gc元方法在这里用于删除LuaWrapped :: Ptr类(它是boost :: shared_ptr的包装器)。我想我会保留它,并将指针存储在普及userdata字段中。


针对正常表的实验性自定义元表问题(根据评论讨论):

void
LuaContext::push(lua_State* state, boost::shared_ptr<LuaWrapped> wrapped) {
    static struct luaL_Reg methods[] = {
        { "__index", LuaWrapped::static_get },
        { "__newindex", LuaWrapped::static_set },
        { "__len", LuaWrapped::static_len },
        { "__ipairs", LuaWrapped::static_ipairs },
        { "__pairs", LuaWrapped::static_pairs },
        { "__gc", LuaWrapped::static_gc },
        { "__eq", LuaWrapped::static_eq },
        { NULL, NULL }
    };

    lua_newtable(state);
    LuaContext::push(state, "pointer");
    lua_pushlightuserdata(state, new LuaWrapped::Ptr(wrapped));
    lua_settable(state, -3);

    lua_newtable(state);
    luaL_openlib(state, NULL, methods, 0);
    lua_setmetatable(state, -2);
}

int
LuaWrapped::static_get(lua_State* state) {
    int argc = lua_gettop(state);
    for (int i = 1; i <= argc; i++) {
        const char *type = lua_typename(state, i);
        std::cout << type << std::endl;
    }
    ....

预期的get输出:

表,字符串

在get上的实际输出(Lua 5.2,Ubuntu 14.04):

布尔,userdata

点赞
用户258523
用户258523

在 userdata 环境/用户值中存储任意数据是它们的作用。

在 Lua 5.2 中,使用 lua_setuservaluelua_getuservalue 函数将表与 userdata 关联起来是实现这一目的的方法。然后,可以使用该表来存储和检索与 userdata 相关的任意值。

在 Lua 5.1 中,更通用的环境概念通过 lua_setfenvlua_getfenv 用于此目的,但思想是相同的。

2015-01-11 23:50:50