Reading Lua nested tables in C++

hal*_*alm 1 c c++ lua nested-table lua-table

我正在创建一个将从Lua调用的C/C++函数.我的函数必须调用一个库函数,其签名是这样的:

void libFunction( int val1, int val2, tSETTINGS * pSettings );
Run Code Online (Sandbox Code Playgroud)

我给了这些C/C++结构.

typedef struct
{
  int cmd;
  int arg;
} tCOMMAND;
typedef struct
{
  int numberCommands;
  int id;
  tCOMMAND commands[1];
} tSETTINGS;
Run Code Online (Sandbox Code Playgroud)

也许我的想法在这方面都是错的,但是从Lua我这样称呼:

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

我确信我仍然不理解从C++引用的Lua堆栈,因为我正在尝试的东西不起作用.我的解决方案能够检索val1,val2,#command和id,但是当我尝试检索命令[0]和命令[ 1 ]时,我分别得到{1,2}和{ 2,42 }.

我的C++基本上就是这样(对于这个样本我正在丢弃这些值).我已经检索了val1和val2:

int stkNdx = 1;
lua_rawgeti(L, 3, stkNdx++ );
int numcmds = lua_tointeger(L, -1);  // this successfully retrieves numberCommands 2
lua_pop(L, 1);
lua_rawgeti(L, 3, stkNdx++ );
int id = lua_tointeger(L, -1);       // this successfully retrieves 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);
Run Code Online (Sandbox Code Playgroud)

我尝试过各种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);
}
Run Code Online (Sandbox Code Playgroud)

该循环执行4次.值2和42的前2次分配给v.接下来的2次迭代跳过赋值(lua_istable返回true).所以看起来虽然我已经检索了numcmdsid,但它们仍然存在于堆栈中.我也很清楚如何在遇到子表时迭代这些子表.

Eni*_*gma 5

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

你的循环应该是:

int cmdNbr = 1;
for( lua_next(L, -2); cmdNbr <= numcmds; cmdNbr++ )
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

或者正如我所说:

lua_rawgeti(L, 3, 2 );
int id = lua_tointeger(L, -1);       // this successfully retrieves id 42
lua_pop(L, 1);

lua_rawgeti(L, 3, 3);
{
    // commands table at stack top
    size_t N = lua_objlen(L,-1); // size of the table

    for (int i = 1; i <= N; ++i)
    {
        lua_rawgeti(L,-1, i); // cmd# at stack top
        {
            lua_rawgeti(L,-1,1); // first entry
            int cmd = lua_tointeger(L,-1);
            lua_pop(L,1);

            lua_rawgeti(L,-1,2); // second entry
            int arg = lua_tointeger(L,-1);
            lua_pop(L,1);
        }
        lua_pop(L, 1); // pop cmd#
    }
}
lua_pop(L, 1); // pop commands table
Run Code Online (Sandbox Code Playgroud)

请注意,使用该功能lua_objlen(L,idx),numcmds无需传递