c++ - 将用户数据元表添加到 lua 表

标签 c++ lua metatable lua-api

我有一个使用用户数据对象运行良好的脚本系统。但是,我现在想在我的用户数据上拥有一个可以采用常规表的属性。

我认为我应该做的是创建一个普通表并将元表设置为使用我当前的一组元方法,但是我正在努力理解如何做到这一点 - 我确信这是一个简单的调整,我可以现在就看到它。

我现有的代码如下:

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 的包装器) .我想我会保留它,并将指针存储在普通表的 lightuserdata 字段中。


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

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 的预期输出:

table, string

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

boolean, userdata

最佳答案

将任意数据与用户数据一起存储是用户数据环境/用户值的用途。

lua 5.2 的方法是使用 lua_setuservaluelua_getuservalue 函数将表与用户数据相关联。该表随后可用于存储和检索与用户数据相关的任意值。

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

关于c++ - 将用户数据元表添加到 lua 表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27890209/

相关文章:

c++ - 如何将模板内部的模板作为模板模板参数传递给另一个模板?

java - 从 C++ 生成 JNI Bridge 和 Java 接口(interface)

regex - 如何在lua中通过正则表达式重复匹配多个表达式

types - Lua 内部是否有可访问的默认类型的表或枚举?

lua - 为什么我们应该使用 lua_pushinteger()?

mysql - 依赖 MySQL 的表注释

C++ 和动态类型语言

c++ - matlab mex 文件和 C++ dll (windows)

Lua - 在元表中只调用一个运算符

oop - Lua 元表类析构函数