将Vector <struct>传递给Lua表

时间:2018-08-23 12:08:21

标签: c++ lua lua-table

我想通过发送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处的表中。元素的索引是counter的值。

但是这里的问题是,我被迫两次调用函数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

我已经对表,元表,多维数组等进行了很多研究,但是找不到适合我的需求或工作的东西。

有人可以解决吗?

2 个答案:

答案 0 :(得分:1)

为什么不让函数返回两个值呢?那你就可以写

[select* email-recipient "Sales|sales@yourdomain.com" "Tech Support|support@yourdomain.com,test2@yourdomain.com" "Inquiry|info@yourdomain.com,test@yourdomain.com"]

我不是C API的专家,但是我认为只需调用local Group = { GetCategories } 就可以很容易地做到这一点,就像这样:

lua_newtable(L)

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

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

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
}

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

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)堆栈溢出而引起的潜在问题。

最后一个细节:在Lua中不需要// 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); } ,除非在一行;中有两个语句,否则使用它们很不好。

答案 1 :(得分:0)

万一有人在寻找类似的东西,这就是我使用lua_createtable进行管理的方式。它可以按预期工作,可能需要一些改进的思想。

int GetCategory(lua_State* L)
    {   
        int counter = 1;
        int MaxListSize = 2;
        auto Categories = sManagerMgr->GetAll();

        lua_createtable(L, Categories.size(), 0);

        for (auto& elem : Categories)
        {
            vector<string> list;
            list.reserve(MaxListSize);

            list.emplace_back(elem->CategoryBrandName);
            list.emplace_back(elem->CategoryName);

            Macro::Push(L, counter); // custom
            lua_createtable(L, 0, MaxListSize);

            for (int i = 1; i <= MaxListSize; i++)
            {
                Macro::Push(L, list.at(i - 1)); // custom
                lua_rawseti(L, -2, i);
            }

            lua_settable(L, -3);
            list.clear();
            counter++;
        }
        return 1;
    }

将产生类似于

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