Comment obtenir le nom du module préchargé en C ++

Je me demande s’il est possible de créer une fonction C ++ qui renvoie (ou affiche) le nom du module préchargé du script actuel.

Par exemple, je voudrais créer la fonction getModuleName() dans le code suivant afin que l’exécution du code puisse imprimer un résultat.

 #include "lua.hpp" void main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_settop(L, 0); luaL_dossortingng(L, "package.preload['A'] = function ()\n" "local a = {}\n" "a.name = my.getModuleName()\n" "print(a.name)\n" "return a end"); luaL_dossortingng(L, "require 'A'\n"); lua_close(L); } 

Comment créer une fonction getModuleName() en C ++?

Si ce n’est pas possible avec C ++, j’aimerais savoir s’il est possible de le faire en Lua.

PS: J’utilise SWIG pour lier le code C ++.

require appelle la fonction de préchargement avec le nom qui lui a été donné comme premier argument.

 #include "lua.hpp" int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_settop(L, 0); luaL_dossortingng(L, "package.preload['A'] = function(this)\n" "local a = {}\n" "a.name = this\n" "print(a.name)\n" "return a end"); luaL_dossortingng(L, "require 'A'\n"); lua_close(L); } 
 $ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2 test.cpp -llua5.2 $ ./a.out A 

Éviter de passer et argumenter

Je ne vois pas pourquoi vous voudriez faire cela, mais c’est facilement faisable en remplaçant la fonction require par votre propre version. Pour simplifier, je ne montre que le code Lua:

 local require_original = require function require(name, ...) current_module = name local val = table.pack(require_original(name, ...)) current_module = nil return table.unpack(val,1,val.n) end package.preload["test"] = function() print("While loading:", current_module) return {} end print("Before loading:", current_module) require("test") print("After loading:", current_module) 
 $ lua5.2 test.lua Before loading: nil While loading: test After loading: nil 

Réponse à la question mal comprise

package.preload est juste une table Lua normale que vous pouvez parcourir comme n’importe quelle autre table Lua de la C-API. Dans ce cas, vous devrez le parcourir deux fois, une fois pour déterminer les précharges qui existent déjà avant d’en append un nouveau, puis de nouveau après avoir ajouté votre préchargement.

 #include  #include  #include  #include "lua.hpp" int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_settop(L, 0); // Determine all existing preloads std::unordered_set known_preloads; lua_getglobal(L, "package"); lua_getfield(L, -1, "preload"); lua_pushnil(L); while (lua_next(L, -2) != 0) { known_preloads.emplace(lua_tossortingng(L, -2)); // pops key lua_pop(L, 1); // pops value } lua_pop(L, 2); // pop preload and package // Add a new preload luaL_dossortingng(L, "package.preload['A'] = function ()\n" "local a = {}\n" "a.name = my.getModuleName()\n" "print(a.name)\n" "return a end"); luaL_dossortingng(L, "require 'A'\n"); // Determine which preloads are new std::unordered_set new_preloads; lua_getglobal(L, "package"); lua_getfield(L, -1, "preload"); lua_pushnil(L); while (lua_next(L, -2) != 0) { std::ssortingng current = lua_tossortingng(L, -2); // pops key if (known_preloads.find(current) == known_preloads.end()) { new_preloads.emplace(current); } lua_pop(L, 1); // pops value } lua_pop(L, 2); // pop preload and package // Print the new preloads for (auto const & preload : new_preloads) { std::cout << preload << '\n'; } lua_close(L); } 

Vous voudrez peut-être envisager d'utiliser Sol2 . C'est l'encapsuleur le plus rapide existant autour de la Lua C-API pour C ++. Cela nécessite du C ++ 14 et ça en vaut la peine. Voyez comment je ne me suis pas inquiété de la stack une seule fois!

 #include  #include  #include  #define SOL_CHECK_ARGUMENTS 1 #include "sol.hpp" int main() { sol::state L; L.open_libraries(); // Determine all existing preloads std::unordered_set known_preloads; L.get("package").get("preload").for_each( [&](sol::object &key, sol::object &) { known_preloads.emplace(key.as()); }); // Add a new preload L.script("package.preload['A'] = function ()\n" "local a = {}\n" "a.name = my.getModuleName()\n" "print(a.name)\n" "return a end"); L.script("require 'A'\n"); // Determine which preloads are new std::unordered_set new_preloads; L.get("package").get("preload").for_each( [&](sol::object &key_, sol::object &) { std::ssortingng key = key_.as(); if (known_preloads.find(key) == known_preloads.end()) { new_preloads.emplace(key); } }); // Print the new preloads for (auto const & preload : new_preloads) { std::cout << preload << '\n'; } }