package.proad在Lua的替代方案



我了解到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);

结果:3

尽管这很好,但我想知道ScriptA的代码是否可以更简化,或者是否有其他替代解决方案可以将脚本公开给其他脚本。

补充:我问这个问题的主要原因是因为我认为package.preload['A'] = function () return A end写起来很长很无聊。

在这种情况下,如果您有一组表示Lua模块的In-C字符串,那么package.preload正是要使用的工具。尽管你对它的具体使用还有待改进。

一般来说,模块本身并不定义它们的名称。因此,将模块名称硬编码到字符串中并不是正确的做法。同样,模块本身也不注册;它们应该由模块周围的环境进行注册。

您真正想要的是获取一个名称+Lua代码字符串的数组,并将它们注册为循环中的模块预加载。所以你会有这样的东西。我将使用Lua 5.3;你可以很容易地把它翻译成旧版本的Lua。

此外,请注意:此代码未经测试。

const char *lua_preloads[] =
{
"A", "local A = {}n"
"A.num = 3n"
"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);

似乎要在定义模块的每个块前面加上local A = {} package.preload['A'] = function () return A end的前缀(其中A是模块名称(。我认为只使用字符串串联会容易得多。

#include <string>
#include <lua.hpp>
int preload(lua_State *L, std::string const &modname,
std::string const &modcode) {
std::string code = "package.preload['" + modname + "'] = function()n" +
"local " + modname + " = {}n" + modcode + "n"
"return " + modname + " end";
return luaL_dostring(L, code.c_str());
}
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// Script A
preload(L, "A", "A.num = 3");
// Script B
luaL_dostring(L, "local A = require 'A' print(A.num)");
lua_close(L);
}

最新更新