lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



On 19-Jan-07, at 9:44 PM, Raymond Jacobs wrote:

Thanks for adding that Chris,

We're a bit closer, I get through one element in the sub-table

however when it goes through and pops off an element and goes to lua_next,

it crashes =/

Have you:
-- made sure that you're running inside of a protected call?
-- enabled Lua's API check feature?

You're making the assumption that all keys are strings; that's certainly not the case. If a key is a number, then the lua_tostring(l, -2) will turn it into a string representation of that number, and lua_next will throw an error since it won't find the resulting string as a key in the table; if you're not running inside of a protected call (which you always should be), then Lua will terminate the application "with extreme prejudice", as it were.

Remember that a table key can be *anything* (except nil and NaN), including another table.



here is the actual code:


void OutputArchive::writeLuaTable(lua_State* l,int idx)
{	
	lua_pushnil(l);
	while(lua_next(l,idx)!=0)
	{
		const char* key=lua_tostring(l,-2);
		int type=lua_type(l,-1);
		switch(type)
		{
		case LUA_TNUMBER:
			writeByte(1);
			writeString(key);
			writeInt(type);
			writeDouble(lua_tonumber(l,-1));
			break;
		case LUA_TSTRING:
			writeByte(1);
			writeString(key);
			writeInt(type);
			writeString(lua_tostring(l,-1));
			break;
		case LUA_TBOOLEAN:
			writeByte(1);
			writeString(key);
			writeInt(type);
			writeBool(lua_toboolean(l,-1)!=0);
			break;
		case LUA_TNIL:
			writeByte(1);
			writeString(key);
			writeInt(type);
			break;
		case LUA_TTABLE:
			{
				writeByte(1);
				writeString(key);	
				writeInt(type);
				writeLuaTable(l,lua_gettop(l));
			}
			break;
		}
		lua_pop(l,1);
	}
}


void OutputArchive::writeLuaState(lua_State* l)
{
	writeLuaTable(l,LUA_GLOBALSINDEX);
}

On 1/19/07, Raymond Jacobs <raymondj@gmail.com> wrote:
Thanks for a quick reply =)

I noticed I wasn't pushing the nil,

my code now looks exactly like yours, but it's still error-ing;

correct me if I'm wrong but,


when you go to recurse, you pass in an index of -1 for lua_next to
use, which is the top of the stack, yet in the function you then push
a nil, which is then at the top of the stack, thus using -1 to
reference the table would be wrong?

-Raymond

On 1/19/07, Jérôme VUARAND <jerome.vuarand@gmail.com> wrote:
> 2007/1/19, Raymond Jacobs <raymondj@gmail.com>:
> > int idx=LUA_GLOBALSINDEX;
> > lua_getfenv(l,idx);
> >
> > while(lua_next(l,idx)!=0)
> > {
> >                 const char* key=lua_tostring(l,-2);
> >
> >                 //get value at -1 index and check type of it
> >
> > //do somthing with key and value based on type of value > > //if value is a table call this function again to traverse it, then
> > continue here
> >
> >
> >                 lua_pop(l,1);
> > }
> >
> > it seems in theory it should be as simple as doing another lua_next, > > however I've not been able to get it to work, and I end up crashing, > > likely due to corupting the stack; either my logic or how I'm going > > about it is wrong, an example of how to do this in the C API would be
> > really helpful.
>
> You forget to push an initial nil on the stack before entering you
> while loop (see lua_next documentation example). Here is what your
> code could look like :
>
> int dosomestuff(lua_State* L, int index)
> {
>     // Do something with value at index (which is not a table)
>     return 1;
> }
>
> int parsetable(lua_State* L, int index)
> {
>     // Push an initial nil to init lua_next
>     lua_pushnil(L);
>     // Parse the table at index
>     while (lua_next(index)!=0)
>     {
>         if (lua_istable(L, -1)
>         {
>             parsetable(L, -1);
>         }
>         else
>         {
>             dosomestuff(L, -1);
>         }
>         // Pop value, keep key
>         lua_pop(L, 1);
>     }
>     return 1;
> }
>
> int parseglobals(lua_State* L)
> {
>     parsetable(L, LUA_GLOBALSINDEX);
>     return 0;
> }
>