Lua C++ 表迭代

我对 lua_next 的工作原理有点困惑。用户定义了一个表:

a={["a1"]=20,["a2"]=30}

我想用 C++ 代码打印这个表:

inline int lua_print(lua_State* L)
{
wxString wxReturnStr=wxEmptyString;
wxString tempString=wxEmptyString;
int nargs = lua_gettop(L);

for (int i=1; i <= nargs; i++)
{
    int type = lua_type(L, i);
    switch (type)
    {

    case LUA_TNIL:
        break;

    case LUA_TBOOLEAN:
        tempString<<(lua_toboolean(L, i) ? "true" : "false");
        break;

    case LUA_TNUMBER:
        tempString<<lua_tonumber(L, i);
        break;

      case LUA_TSTRING:
          tempString<<lua_tostring(L, i);
        break;
      case LUA_TTABLE:
      {
          lua_pushnil(L);
          while(lua_next(L,-2))
          {
                const char* key=lua_tostring(L,-2);
                double val=lua_tonumber(L,-1);
                lua_pop(L,1);
                tempString<<key<<"="<<val<<"\t";
          }

          break;
      }

      default:
          tempString<<lua_typename(L, type);
        break;
    }

    wxReturnStr=wxReturnStr+tempString+"\n";
    tempString=wxEmptyString;

}

lua_pop(L,nargs);

当我在 Lua 中调用它时,它运行得很好:

print(a) -- 运行良好

然而,假设我在 Lua 中有一个表:

b={["b1"]=10, ["b2"]=15}

如果我像这样调用代码:

print(a,b) -- 会两次打印 b 的内容

我的理解是 lua_next 的工作原理如下图所示:enter image description here【第一版】

哪里出问题了?

点赞
用户478271
用户478271

你在处理完表格后忘记了执行lua_pop

lua_pushnil(L);
while(lua_next(L,-2))
{
      const char* key=lua_tostring(L,-2);
      double val=lua_tonumber(L,-1);
      lua_pop(L,1);
      tempString<<key<<"="<<val<<"\t";
}
lua_pop(L, 1); // 修复了问题,弹出了用于处理表格的栈上的 nil

这意味着,多余的 nil 保留在栈上,所以在第二次迭代中,

case LUA_TNIL:
   break;

什么也不会输出。

关于你对栈的图形表示。每个图像下面的命令代表执行命令后的状态。因此,最后一个图像在栈上缺少[Key = a2]。

2015-06-19 13:12:01
用户3125367
用户3125367

bug 出现在 lua_next(L, -2) 这一行,因为 -2 指的是栈顶的倒数第二个元素,而这里的最后一个参数正好是 print 函数的参数。

请使用 lua_next(L, i) 代替。

更新:在开发阶段移动代码时,Lua 堆栈索引可能会发生浮点数的变化,因此通常建议在获取/推送/考虑参数值之后用一个小整形 int t = lua_gettop(L) 固定索引,并使用 t 代替 -n(尽管这个特定情况似乎是一个打错字的错误)。

2015-06-19 14:25:43