我了解到package.preload可以用来将一个脚本公开给其他脚本。
这是我的示例代码。
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_settop(L, 0);
//Script A
luaL_dostring(L, "local A = {} package.preload['A'] = function () return A end A.num = 3");
//Script B
luaL_dostring(L, "local A = require 'A' print(A.num)");
lua_close(L);
Run Code Online (Sandbox Code Playgroud)
结果:3
虽然这工作正常,但我想知道 ScriptA的代码是否可以更加简化,或者是否有其他替代解决方案将脚本公开给其他脚本。
补充:我问这个的主要原因是因为我认为package.preload['A'] = function () return A end写起来很长而且很无聊。
在这种情况下,如果您有一组代表 Lua 模块的 C 语言字符串,package.preload那么这正是要使用的工具。尽管您对它的具体使用还有一些不足之处。
一般来说,模块本身并没有定义它们的名称。因此,将模块名称硬编码到字符串中并不是正确的做法。同样,模块不会自行注册;它们应该由模块周围的环境注册。
你真正想要的是获取一个名称+Lua代码字符串的数组,并将它们注册为循环中的模块预加载。所以你会有这样的东西。我将使用 Lua 5.3;你可以很容易地将它翻译成旧版本的 Lua。
另外,请注意:此代码未经测试。
const char *lua_preloads[] =
{
"A", "local A = {}\n"
"A.num = 3\n"
"return A)\n", //Modules are usually tables, not functions.
...
NULL //Null-terminated list.
};
//Loader function
int lua_preloader_func(lua_State *L)
{
int nargs = lua_gettop(L);
int lua_func_ix = lua_upvalueindex(1);
lua_pushvalue(L, lua_func_ix);
//Move the function to the bottom of the stack
lua_insert(lua_func_ix, 1);
//Call with all of the given arguments.
lua_call(L, nargs, LUA_MULTRET);
return lua_gettop(L);
}
int top = lua_gettop(L);
//Get the package.preload table.
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");
int preload_ix = lua_gettop();
for(const char **position = lua_preloads;
*position;
position += 2)
{
const char *module_name = position[0];
const char *module = position[1];
//Compile the preload script into a Lua function.
int err = luaL_loadbufferx(L, module, strlen(module), module_name, "t");
//Check for errors in `err`.
//Create a Lua C-function with the script as an upvalue.
lua_pushcclosure(L, lua_preloader_func, 1);
//Stick that Lua C-function inside of package.preload[preload.first].
lua_setfield(L, preload_ix, module_name);
}
lua_settop(L, top);
Run Code Online (Sandbox Code Playgroud)