首页 > 解决方案 > 传递向量到 Lua 表

问题描述

我想通过发送一个 C++ 预格式化的 Lua 表来改进我的代码:

int GetCategory(lua_State* L)
{
    uint32 Type = CHECKVAL<int>(L, 1);
    lua_newtable(L); 
    int tbl = lua_gettop(L);
    uint32 counter = 1;
    // Struct CT { string CategoryBrandName, CategoryName }; > Vector<CT>
    auto list = sManagerMgr->GetAll(); 


    // Hack modify this to send a metatable/UserData/Table whatever is called
    for (auto& elem : list)
    {
        switch (Type)
        {
        case 1:
            lua_pushstring(L, elem->CategoryBrandName);
            break;
        case 2:
            lua_pushstring(L, elem->CategoryName);
            break;
        }
        lua_rawseti(L, tbl, counter);
        counter++;
    }

    lua_settop(L, tbl);
    return 1;
}

基本上,lua_newtable 将一个表推送到 lua 堆栈中,lua_gettop 将取顶部索引,即表所在的索引。然后 lua_pushstring(L, ELEMENT); lua_rawseti(L, tbl, 计数器); 将 ELEMENT 放到我们使用 gettop 获得的索引 tbl 处的表中。元素的索引是计数器的值。

但是这里的问题是我不得不调用两次函数 GetCategory 来填充它,如下所示在我的 .lua 文件中。

table.insert(Group, { GetCategory(1), GetCategory(2) });

当前用途:

print(i, Group(1)[i], Group(2)[i]);

所以..我宁愿调用一次并直接得到这样的东西:

local Group = 
{ 
        [1] = { "elem->CategoryBrandName[1]", "elem->CategoryName[1]" },
        [2] = { "elem->CategoryBrandName[2]", "elem->CategoryName[2]" }
        --etc
};

我尝试将 elem 填充到 2D Array[1][2] 中,然后推送 Array 失败

我对表、元表、多维数组等进行了大量研究,但找不到适合我需要或工作的东西。

有没有人有解决方案?

标签: c++lualua-table

解决方案


你为什么不让你的函数返回两个值?然后你可以写

local Group = { GetCategories }

我不是 C API 方面的专家,但我认为这可以通过调用来相当容易地完成lua_newtable(L),所以像这样:

int GetCategories(lua_State* L) {
  lua_settop(L, 0);
  // Discard arguments so we don't have to save the top of the stack
  // and can just use numbers instead (see following lines)
  lua_newtable(L); // Index 1 on stack
  lua_newtable(L); // Index 2 on stack

  // Do your magic

  lua_settop(L, 2); // Get rid of your temp variables
  return 2; // number of values we return in Lua
}

优化提示:您可以使用lua_createtable并告诉它每个表将有多少元素,以便 Lua 可以为其预先分配一些内存。

编辑:我刚刚注意到这一点,但在你的代码中:

for (auto& elem : list) {
  switch (Type) {
  case 1:
    lua_pushstring(L, elem->CategoryBrandName);
    break;
  case 2:
    lua_pushstring(L, elem->CategoryName);
    break;
  }
  lua_rawseti(L, tbl, counter);
  counter++;
}

您只需将值推入堆栈即可。对于长向量,这可能会溢出堆栈(迟早),导致麻烦。更好的方法是 1) 推送到堆栈 2) 插入表 3) 将它们弹出:

// Modified for my suggested implementation that returns
// two tables. They can easily be turned around here.
for (auto& elem : list) {
  lua_pushstring(L, elem->CategoryBrandName);
  lua_rawseti(L, 1, counter++);
  lua_pop(L, 1);

  lua_pushstring(L, elem->CategoryName);
  lua_rawseti(L, 2, counter++);
  lua_pop(L, 1);
}

了解堆栈中的内容和不在堆栈中的内容总是一个好主意。节省一些内存不仅可以提高性能,还可以避免由于(Lua)堆栈溢出而导致的潜在问题。

最后一个细节:你不需要;在 Lua 中,除非你在一行中有两个语句,否则使用它们被认为是不好的风格print('more readable'); print('like this')


推荐阅读