Lua 数组和对象在相同的 userdata 内的访问

我有一个以 C++ 编写的 CArray 类,并将其作为数组暴露给 Lua。

1) 创建新的 userdata:

int Array_new(lua_State* L)
{
    int len = luaL_checkint(L, 1);
    CArray<std::string> **Arr = (CArray<std::string>**)lua_newuserdata(L, sizeof(CArray<std::string>*));
    *Arr = new CArray<std::string>(len);
    luaL_getmetatable(L, "ArrayMetatable");
    lua_setmetatable(L, -2);

    return 1;
}

2) 访问元素:

int Array_getValue(lua_State* L)
{
    CArray<std::string>* arr = *(CArray<std::string>**)lua_touserdata(L, 1);
    int pos=luaL_checknumber(L, 2)-1;

    //为了简洁省略
    lua_pushstring(L, stdStr.c_str());

    return 1;
}

3) 在 Lua 中注册:

int luaopen_Array(lua_State* L)
{
    luaL_newmetatable(L, "ArrayMetatable"); // metatable1

    luaL_setfuncs(L, Array_metatable, 0);
    lua_pushstring(L, "__index");
    lua_pushvalue(L, -2);  //  metatable1 __index metatable1
    lua_settable(L, -3); // metatable1[__index]=metatable1

    /*luaL_newmetatable(L, "ArrayMetatable_2"); //  metatable1 metatable2
    lua_pushstring(L, "__index"); //  metatable1 metatable2 __index
    lua_pushstring(L, "get"); //  metatable1 metatable2 __index get
    lua_gettable(L, 1);  //  metatable1 metatable2 __index
    lua_settable(L, 2);

    lua_pushvalue(L, 1); //metatable1 metatable2 metatable1*/

    lua_setglobal(L, "Array");

    return 0;
}

问题是我必须优先使用 Lua 代码来访问数组中的元素: a) arr:get(1) 获取第一个元素,b) arr[1] 获取第一个元素。

然而 ab 无法同时工作,所以我必须优先选择 样式 a样式 b。是否可以通过修改第三步来同时执行 ab

到目前为止,我所提供的代码在 第二步 如果尝试使用类似于 arr[2] 的 Lua 表达式,将会出现错误,其中变量arr的地址为 0xcccccc。

点赞
用户2420301
用户2420301

你可以添加一个 __index 方法和一个 get 方法,只需将它们分别添加即可。

2017-10-22 08:10:21
用户5129715
用户5129715

注册函数看起来有点混乱。

通常你需要两个元表 - 全局函数和成员函数。

static const struct luaL_Reg Array_globals[] = {
    { "new", Array_new },
    { NULL,NULL }
};

static const struct luaL_Reg Array_members[] = {
    { "get", Array_getValue},
    { "__index", Array_getValue },
    { NULL,NULL }
};

luaopen_函数只需使用相应的方法构建表。我建议还编写 __len__setindex

int luaopen_Array(lua_State* L)
{
    luaL_newmetatable(L, "ArrayMetatable"); // metatable1

    luaL_setfuncs(L, Array_members, 0);

    luaL_newlib( L, Array_globals );
    return 1; // 返回表给调用者。
}
2017-10-23 19:34:24