Share Tableau entre lua et c

J’ai vraiment googlé cette question mais je n’ai jamais vraiment eu de solution.

Je souhaite partager un tableau entre C et Lua. Pour éviter les performances, je ne vais pas copier les tableaux vers et depuis Lua.

Donc, je veux passer un pointeur sur le tableau de C à Lua. Et puis de Lua je veux définir / modifier les valeurs dans ce tableau directement.


Exemple en code C

Je veux définir mon tableau

int mydata[] = {1,2,3,4} 

paramétrez-le globalement pour y accéder depuis Lua avec le nom mydata .


À Lua

Je veux changer les valeurs comme ça

 mydata[3] = 9 

et quand je reviens en C, mydata[3] vaut 9 parce que c’est un pointeur sur le tableau.

Comment est-ce possible?

    Vous pouvez exposer des données arbitraires à Lua via userdata . Si vous atsortingbuez une valeur à vos valeurs de données utilisateur, vous pouvez définir le comportement de différents opérateurs / opérations sur ces données utilisateur. Dans ce cas, nous voulons exposer un tableau à Lua et définir quoi faire dans le cas de array[index] et array[index] = value .

    Nous exposons le tableau à Lua en créant un tampon userdata suffisamment grand pour contenir l’adresse du tableau. Nous définissons le comportement d’indexation / affectation en créant un métatable avec les méthodes __index et __newindex .

    Vous trouverez ci-dessous un exemple de travail complet exposant un tableau statique à Lua. Votre programme aura probablement un autre appel pour renvoyer le tableau à Lua. Remarquez, il n’y a pas du tout de limite; si vous essayez d’indexer en dehors des limites du tableau, vous allez tomber en panne. Pour rendre cela plus robuste, vous voudriez changer les données utilisateur en une structure qui a le pointeur et la taille du tableau, afin que vous puissiez faire le boundshecking.

     #include "lauxlib.h" // metatable method for handling "array[index]" static int array_index (lua_State* L) { int** parray = luaL_checkudata(L, 1, "array"); int index = luaL_checkint(L, 2); lua_pushnumber(L, (*parray)[index-1]); return 1; } // metatable method for handle "array[index] = value" static int array_newindex (lua_State* L) { int** parray = luaL_checkudata(L, 1, "array"); int index = luaL_checkint(L, 2); int value = luaL_checkint(L, 3); (*parray)[index-1] = value; return 0; } // create a metatable for our array type static void create_array_type(lua_State* L) { static const struct luaL_reg array[] = { { "__index", array_index }, { "__newindex", array_newindex }, NULL, NULL }; luaL_newmetatable(L, "array"); luaL_openlib(L, NULL, array, 0); } // expose an array to lua, by storing it in a userdata with the array metatable static int expose_array(lua_State* L, int array[]) { int** parray = lua_newuserdata(L, sizeof(int**)); *parray = array; luaL_getmetatable(L, "array"); lua_setmetatable(L, -2); return 1; } // test data int mydata[] = { 1, 2, 3, 4 }; // test routine which exposes our test array to Lua static int getarray (lua_State* L) { return expose_array( L, mydata ); } int __declspec(dllexport) __cdecl luaopen_array (lua_State* L) { create_array_type(L); // make our test routine available to Lua lua_register(L, "array", getarray); return 0; } 

    Usage:

     require 'array' foo = array() print(foo) -- userdata -- initial values set in C print(foo[1]) print(foo[2]) print(foo[3]) print(foo[4]) -- change some values foo[1] = 2112 foo[2] = 5150 foo[4] = 777 -- see changes print(foo[1]) print(foo[2]) print(foo[3]) print(foo[4])