在C++中读取Lua嵌套表。

我正在创建一个 C/C++ 函数,它将从 Lua 调用。我的函数必须调用一个库函数,其签名如下:

void libFunction( int val1, int val2, tSETTINGS * pSettings );

我有以下 C/C++ 结构:

typedef struct
{
    int cmd;
    int arg;
} tCOMMAND;
typedef struct
{
    int numberCommands;
    int id;
    tCOMMAND commands[1];
} tSETTINGS;

也许我的想法是错的,但是我从 Lua 调用方式如下:

id   = 42
val1 = 1
val2 = 2
cmd1 = { 3, 4 }
cmd2 = { 5, 6 }
commands = { cmd1, cmd2 }
settings = { #commands, id, commands }
mycfunction( val1, val2, settings )

我确定我仍然不理解从 C++ 引用的 Lua 栈,因为我正在尝试的东西并不起作用。我能够检索到 val1val2#commandsid,但是当我尝试检索 commands[0]commands[1] 时,我分别得到了 {1, 2}{2, 42}

我的 C++ 代码本质上是这样的(针对此示例,我正在放弃值)。我已经检索到了 val1val2

int stkNdx = 1;
lua_rawgeti(L, 3, stkNdx++ );
int numcmds = lua_tointeger(L, -1);  // 这可以成功检索到 numberCommands 2
lua_pop(L, 1);
lua_rawgeti(L, 3, stkNdx++ );
int id = lua_tointeger(L, -1);       // 这可以成功检索到 id 42
lua_pop(L, 1);

lua_pushvalue(L, -1 );
lua_pushnil(L);
int cmdNbr = 0;
for( lua_next(L, -2); cmdNbr < numcmds; cmdNbr++ )
{
    lua_pushvalue(L, -2);
    int cmd = lua_tointeger(L, -1);
    int arg = lua_tointeger(L, -1);
    lua_pop(L, 2);
    lua_next(L, -2);
}
lua_pop(L, 1);

我已经尝试了 lua_rawgeti() 后跟 lua_tonumber()lua_pop() 的各种排列组合,结果基本相同。

这似乎类似于 这个问题,我的解决方案就是模仿它,但没有成功。

更多的实验让我插入了这个:

lua_pushnil(L);
while( lua_next(L, -2) )
{
    if( ! lua_istable(L, -1) )
    {
        int v = lua_tointeger(L, -1);
    }
    lua_pop(L, 1);
}

这个循环执行了 4 次。前两次将值 2 和 42 赋给了 v。下两次迭代跳过了赋值(lua_istable 返回 true)。所以看来尽管我已经检索了 numcmdsid,它们仍然留在栈中。我也很明显不理解遇到子表时如何进行迭代。

点赞
用户2458544
用户2458544

Lua表索引范围是[1 .. N],而不是[0 .. N-1]。

你的循环应该是这样的:

int cmdNbr = 1;
for( lua_next(L, -2); cmdNbr <= numcmds; cmdNbr++ )
{
  ...
}

或者我更喜欢的:

lua_rawgeti(L, 3, 2 );
int id = lua_tointeger(L, -1);       // 这一步成功地检索到了id 42
lua_pop(L, 1);

lua_rawgeti(L, 3, 3);
{
    // table在栈顶
    size_t N = lua_objlen(L,-1); // 获取table大小

    for (int i = 1; i <= N; ++i)
    {
        lua_rawgeti(L,-1, i); // cmd# 在栈顶
        {
            lua_rawgeti(L,-1,1); // 第一个条目
            int cmd = lua_tointeger(L,-1);
            lua_pop(L,1);

            lua_rawgeti(L,-1,2); // 第二个条目
            int arg = lua_tointeger(L,-1);
            lua_pop(L,1);
        }
        lua_pop(L, 1); // 弹出cmd#
    }
}
lua_pop(L, 1); // 弹出commands table

请注意,使用函数lua_objlen(L,idx),不需要传递numcmds参数。

2013-06-07 06:51:41