您需要注意两件事:
- 确保在下一次调用
lua_next
. luaL_checkstring
将非字符串键转换为字符串(因为结果字符串不在表中,它成为无效键。)这最容易通过传递luaL_checkstring
键的副本而不是原始键来完成。
- 确保在每次通过循环时保留堆栈结构(即弹出尽可能多的值)
您的函数仅适用于 的负值index
。你是正确的,这index--;
将确保index
在按下键后仍然指向表,但只有当它index
是负数时(即相对于堆栈的顶部)。如果index
是绝对索引或伪索引,那么它将导致它指向错误的项目。最简单的解决方法是将另一个对表的引用推送到堆栈顶部。
这是一个用于演示的最小 C 程序:
#include <lauxlib.h>
#include <lua.h>
static void iterate_and_print(lua_State *L, int index);
int main(int ac, char **av)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// Create a table and put it on the top of the stack
luaL_loadstring(L, "return {one=1,[2]='two',three=3}");
lua_call(L, 0, 1);
iterate_and_print(L, -1);
return 0;
}
static void iterate_and_print(lua_State *L, int index)
{
// Push another reference to the table on top of the stack (so we know
// where it is, and this function can work for negative, positive and
// pseudo indices
lua_pushvalue(L, index);
// stack now contains: -1 => table
lua_pushnil(L);
// stack now contains: -1 => nil; -2 => table
while (lua_next(L, -2))
{
// stack now contains: -1 => value; -2 => key; -3 => table
// copy the key so that lua_tostring does not modify the original
lua_pushvalue(L, -2);
// stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
const char *key = lua_tostring(L, -1);
const char *value = lua_tostring(L, -2);
printf("%s => %s\n", key, value);
// pop value + copy of key, leaving original key
lua_pop(L, 2);
// stack now contains: -1 => key; -2 => table
}
// stack now contains: -1 => table (when lua_next returns 0 it pops the key
// but does not push anything.)
// Pop table
lua_pop(L, 1);
// Stack is now the same as it was on entry to this function
}