如何在C++中获得预加载的模块名称
How to get preloaded module name in C++
我想知道是否可以创建一个C++函数来返回(或打印(当前脚本的预加载模块名称。
例如,我想在下面的代码中创建getModuleName()
函数,这样运行代码就可以打印A
。
#include "lua.hpp"
void main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_settop(L, 0);
luaL_dostring(L, "package.preload['A'] = function ()n"
"local a = {}n"
"a.name = my.getModuleName()n"
"print(a.name)n"
"return a end");
luaL_dostring(L, "require 'A'n");
lua_close(L);
}
如何在C++中创建getModuleName()
函数?
如果用C++做不到,我想知道用Lua做是否可能。
p.S:我正在使用SWIG绑定C++代码。。
require
使用作为第一个参数的名称调用预加载函数。
#include "lua.hpp"
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_settop(L, 0);
luaL_dostring(L, "package.preload['A'] = function(this)n"
"local a = {}n"
"a.name = thisn"
"print(a.name)n"
"return a end");
luaL_dostring(L, "require 'A'n");
lua_close(L);
}
$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2 test.cpp -llua5.2
$ ./a.out
A
避免传递和争论
我不明白你为什么要这样做,但通过用你自己的版本覆盖require
函数,这很容易实现。为了简单起见,我只显示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
误解问题的答案
package.preload
只是一个常规的Lua表,您可以像C-API中的任何其他Lua表一样遍历它。在这种情况下,您将不得不遍历它两次,一次是在添加新的预加载之前确定哪些预加载已经存在,然后在添加预加载之后再次遍历。
#include <iostream>
#include <string>
#include <unordered_set>
#include "lua.hpp"
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_settop(L, 0);
// Determine all existing preloads
std::unordered_set<std::string> known_preloads;
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
known_preloads.emplace(lua_tostring(L, -2)); // pops key
lua_pop(L, 1); // pops value
}
lua_pop(L, 2); // pop preload and package
// Add a new preload
luaL_dostring(L, "package.preload['A'] = function ()n"
"local a = {}n"
"a.name = my.getModuleName()n"
"print(a.name)n"
"return a end");
luaL_dostring(L, "require 'A'n");
// Determine which preloads are new
std::unordered_set<std::string> new_preloads;
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
std::string current = lua_tostring(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);
}
您可能需要考虑使用Sol2。它是目前存在的围绕C++的Lua-C-API最快的包装器。它需要C++14,这完全值得。看看我一次都不担心堆栈!
#include <iostream>
#include <string>
#include <unordered_set>
#define SOL_CHECK_ARGUMENTS 1
#include "sol.hpp"
int main() {
sol::state L;
L.open_libraries();
// Determine all existing preloads
std::unordered_set<std::string> known_preloads;
L.get<sol::table>("package").get<sol::table>("preload").for_each(
[&](sol::object &key, sol::object &) {
known_preloads.emplace(key.as<std::string>());
});
// 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<std::string> new_preloads;
L.get<sol::table>("package").get<sol::table>("preload").for_each(
[&](sol::object &key_, sol::object &) {
std::string key = key_.as<std::string>();
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';
}
}
相关文章:
- 当我尝试加载内核模块时,如何修复C++中的这个 malloc() 错误?
- 如何在没有"路径"模块的情况下加载 cheerp-wasm 程序?
- 无法加载 QML 插件:无法保护模块,因为它从未注册过
- 如何在C++中获得预加载的模块名称
- 如果我想通过OpenCV dnn模块加载PyTorch的模型,我应该如何保存它
- 在FreesWitch中使用AWS C SDK加载模块时未定义的符号错误
- 在 Lua 中加载 C++ 模块时'Attempt to index a string value'错误
- 地址清理器和运行时加载动态库 ->(<未知模块>)
- 将所有模块加载到过程中,然后将其出口
- 保存和加载我的模块
- Visual Studio 在附加到进程时不会加载模块
- C# 无法加载 DLL(找不到模块结果:0x8007007E)
- 在模块加载/卸载时构造/破坏外部c++模块中的对象
- LD_PRELOAD应该加载模块还是只使用模块来替换符号
- Python C API-重新加载模块
- DLL 无法加载:0x8007007E找不到模块。不确定导致此依赖项问题的原因
- 加载程序如何从动态模块分配/取消分配静态数据
- 模块"MyShellExt.dll"加载失败
- 为什么要在运行时加载模块?
- LoopPass可加载模块的未定义符号