Itérer à travers la table de Lua

J’essaye de parcourir une table Lua mais je continue à avoir cette erreur:

invalid key to 'next' 

Je sais que l’indice commence par -8 et je sais qu’il y a une table car il y a la première (et la seule) valeur. Cependant, il essaie de tourner en boucle encore une fois, même si je sais qu’il n’ya qu’une chaîne dans la table.

 if (lua_istable(L, index)) { lua_pushnil(L); // This is needed for it to even get the first value index--; while (lua_next(L, index) != 0) { const char *item = luaL_checkssortingng(L, -1); lua_pop(L, 1); printf("%s\n", item); } } else { luaL_typerror(L, index, "ssortingng table"); } 

Toute aide serait appréciée.

Cela fonctionne bien lorsque j’utilise un index positif (tant que je n’en retire pas 1)

Edit: J’ai remarqué que je ne reçois pas cette erreur si je laisse la valeur de item seule. Ce n’est que lorsque je commence à lire la valeur de item que j’obtiens cette erreur. Quand j’ai la valeur de la table, j’appelle une autre fonction Lua, cela pourrait-il perturber lua_next?

N’utilisez pas luaL_checkssortingng avec des arguments négatifs. Utilisez plutôt lua_tossortingng .

Assurez-vous également que la stack rest la même après avoir appelé une fonction de la boucle: lua_next attend la clé de table précédente en haut de la stack pour pouvoir reprendre la traversée.

Il y a 2 choses que vous devez regarder:

  • Assurez-vous que la clé d’origine est laissée sur la stack avant le prochain appel à lua_next . luaL_checkssortingng convertira les clés non-chaîne en chaînes (la chaîne résultante ne se luaL_checkssortingng pas dans la table, elle devient une clé non valide). Pour ce faire, luaL_checkssortingng copie luaL_checkssortingng une copie de la clé au lieu de la clé d’origine.
  • assurez-vous de conserver la structure de la stack (c.-à-d. que vous enfoncez autant de valeurs que vous le souhaitez) à chaque passage dans la boucle

Votre fonction ne fonctionnera que pour les valeurs négatives d’ index . Vous avez raison cet index--; s’assurera que index pointe toujours sur la table après avoir appuyé sur la touche, mais uniquement si index est négatif (c.-à-d. par rapport au haut de la stack.) Si index est un index absolu ou pseudo, il sera alors dirigé vers le mauvais article. La solution de contournement la plus simple consiste à placer une autre référence à la table en haut de la stack.

Voici un programme C minimal pour démontrer:

 #include  #include  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_loadssortingng(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_tossortingng does not modify the original lua_pushvalue(L, -2); // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table const char *key = lua_tossortingng(L, -1); const char *value = lua_tossortingng(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 } 

Du manuel :

 const char *lua_tolssortingng (lua_State *L, int index, size_t *len); 

Convertit la valeur Lua à l’index acceptable donné en chaîne C. Si len n’est pas NULL, il définit également * len avec la longueur de la chaîne. La valeur Lua doit être une chaîne ou un nombre. sinon, la fonction retourne NULL. Si la valeur est un nombre, lua_tolssortingng modifie également la valeur réelle dans la stack en chaîne. (Cette modification confond lua_next lorsque lua_tolssortingng est appliqué aux clés lors du parcours d’une table.)

luaL_checkssortingng appelle lua_tolssortingng .

Voir aussi l’exemple de la documentation pour lua_next , extrait ici:

int lua_next (lua_State *L, int index);

Enlève une clé de la stack et pousse une paire clé-valeur de la table à l’index donné (la paire “suivante” après la clé donnée). S’il n’y a plus d’éléments dans la table, alors lua_next renvoie 0 (et ne met rien).

Un parcours typique ressemble à ceci:

 /* table is in the stack at index 't' */ lua_pushnil(L); /* first key */ while (lua_next(L, t) != 0) { /* uses 'key' (at index -2) and 'value' (at index -1) */ printf("%s - %s\n", lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1))); /* removes 'value'; keeps 'key' for next iteration */ lua_pop(L, 1); } 

lua_tolssortingng une table, n’appelez pas lua_tolssortingng directement sur une clé, sauf si vous savez que la clé est en réalité une chaîne. Rappelez-vous que lua_tolssortingng peut changer la valeur à l’index donné; cela confond le prochain appel à lua_next .

Voir la fonction next pour les mises en garde relatives à la modification de la table pendant son parcours.