lua-users home
lua-l archive

Re: recursively traverse globals table from C API

[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;
> }
>

AltStyle によって変換されたページ (->オリジナル) /