Comment travailler avec des tables passées en tant qu’argument à une fonction lua C?

Je vais implémenter une fonction avec le langage C et qui sera appelée par le script Lua.

Cette fonction devrait recevoir une table lua comme argument, je devrais donc lire les champs de la table.J’essaie de faire comme ci-dessous, mais ma fonction se bloque lorsque je l’exécute. Quelqu’un peut-il m’aider à trouver le problème?

/* function findImage(options) imagePath = options.imagePath fuzzy = options.fuzzy ignoreColor = options.ignoreColor; end Call Example: findImage {imagePath="/var/image.png", fuzzy=0.5, ignoreColor=0xffffff} */ // implement the function by C language static int findImgProxy(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); lua_getfield(L, -1, "imagePath"); if (!lua_isssortingng(L, -1)) { error(); } const char * imagePath = lua_tossortingng(L, -2); lua_pop(L, 1); lua_getfield(L, -1, "fuzzy"); if (!lua_isnumber(L, -1)) { error(); } float fuzzy = lua_tonumber(L, -2); lua_getfield(L, -1, "ignoreColor"); if (!lua_isnumber(L, -2)) { error(); } float ignoreColor = lua_tonumber(L, -2); ... return 1; } 

Que diriez-vous de retourner une table de C à Lua:

struct Point { int x, y; } typedef Point Point; static int returnImageProxy(lua_State *L) { Point points[3] = {{11, 12}, {21, 22}, {31, 32}}; lua_newtable(L); for (int i = 0; i 3; i++) { lua_newtable(L); lua_pushnumber(L, points[i].x); lua_rawseti(L, -2, 0); lua_pushnumber(L, points[i].y); lua_rawseti(L, -2, 1); lua_settable(L,-3); } return 1; // I want to return a Lua table like :{{11, 12}, {21, 22}, {31, 32}} }
struct Point { int x, y; } typedef Point Point; static int returnImageProxy(lua_State *L) { Point points[3] = {{11, 12}, {21, 22}, {31, 32}}; lua_newtable(L); for (int i = 0; i 3; i++) { lua_newtable(L); lua_pushnumber(L, points[i].x); lua_rawseti(L, -2, 0); lua_pushnumber(L, points[i].y); lua_rawseti(L, -2, 1); lua_settable(L,-3); } return 1; // I want to return a Lua table like :{{11, 12}, {21, 22}, {31, 32}} } 

    Lorsque vous travaillez avec l’API C de Lua, il est important de vous familiariser avec la stack virtuelle: toutes les interactions importantes entre les limites de langage s’y déroulent. En examinant votre extrait de code, vous n’avez pas l’impression que vous rassemblez correctement les données sur C.

    Lorsque vous écrivez une fonction Lua C, vous devez faire essentiellement 3 choses:

    • Convertissez les données Lua d’entrée en quelque chose avec lequel vous pouvez travailler en C.
    • Effectuer le traitement ou tout ce que la fonction doit faire.
    • Convertissez et renvoyez le résultat de sortie éventuel en lua.

    À titre d’exemple, voici à quoi devrait ressembler votre findImgProxy :

     static int findImgProxy(lua_State *L) { // discard any extra arguments passed in lua_settop(L, 1); luaL_checktype(L, 1, LUA_TTABLE); // Now to get the data out of the table // 'unpack' the table by putting the values onto // the stack first. Then convert those stack values // into an appropriate C type. lua_getfield(L, 1, "imagePath"); lua_getfield(L, 1, "fuzzy"); lua_getfield(L, 1, "ignoreColor"); // stack now has following: // 1 = {imagePath="/var/image.png", fuzzy=0.5, ignoreColor=0xffffff} // -3 = "/var/image.png" // -2 = 0.5 // -1 = 0xffffff const char *imagePath = luaL_checkssortingng(L, -3); double fuzzy = luaL_checknumber(L, -2); int ignoreColor = luaL_checkint(L, -1); // we can pop fuzzy and ignoreColor off the stack // since we got them by value lua_pop(L, 2); // do function processing // ... return 1; } 

    Notez que nous devons garder imagePath sur la stack car nous y tenons un const char * . Couper cette chaîne invaliderait *imagePath puisque lua pourrait la collecter.

    Vous pouvez également copier la chaîne renvoyée par luaL_checkssortingng dans un autre tampon. Dans ce cas, il est correct de supprimer la chaîne car nous ne pointons plus vers un tampon interne appartenant à lua.

    Edit: Si certaines des clés de la table sont facultatives, vous pouvez utiliser les fonctions luaL_opt* place et fournir des valeurs par défaut. Par exemple, si fuzzy et ignoreColor sont facultatifs:

      // ... const char *imagePath = luaL_checkssortingng(L, -3); double fuzzy = luaL_optnumber(L, -2, 0.0); // defaults to 0.0 if no fuzzy int ignoreColor = luaL_optint(L, -1, 0); // defaults to 0 if no ignoreColor // ... 

    Donc, si le code appelant fournit une valeur absurde pour une clé, cela provoquera toujours une erreur. OTOH, s’il est absent, la valeur est nil et la valeur fournie par défaut est utilisée à la place.