macroland
macroland

Reputation: 1035

Lua C++ Table Iteration

I am having a slight confusion of how lua_next really works. User defines a table:

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

I want to print this table with a C++ code:

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);

This code works very well when I call from Lua:

print(a) -- Works well

However, imagine I have a table in Lua as:

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

if I call the code as:

print(a,b) -- Twice prints only contents of b 

My understanding with how lua_next work is in the following figure:enter image description here [Edition #1]

Where is the bug?

Upvotes: 5

Views: 2581

Answers (2)

user3125367
user3125367

Reputation: 3000

The bug is in lua_next(L, -2) line, because -2 refers to stack top minus one, which happens here to be the last argument to print.

Use lua_next(L, i) instead.

Upd: Lua stack indexes are subject to float when moving code around at development stage, so the general advice is to pin indexes with sml int t = lua_gettop(L) just after getting/pushing/considering values and to use that t instead of -n (though this specific case appears to be sort of a keystroke bug.)

Upvotes: 4

kovarex
kovarex

Reputation: 1830

You forgot the lua_pop after processing the table.

 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); // THE FIX, pops the nil on the stack used to process the table

This means, that extra nil is left on the stack, so in the second iteration, the

case LUA_TNIL:
   break;

just prints nothing.

About your graphics representation of the stack. The command under each image represents the state after the command was called. So the very last image is missing the [Key = a2] item on the stack.

Upvotes: 1

Related Questions