用preload加载Lua导出模块
(金庆的专栏 2017.5)
参考:
How to make exported module non-global?
https://github.com/SteveKChiu/lua-intf/issues/135
动态库可以这样导出模块:
extern "C"
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CODEGEARC__)
__declspec(dllexport)
#endif
int luaopen_modname(lua_State* L)
{
LuaRef mod = LuaRef::createTable(L);
LuaBinding(mod)
...;
mod.pushToStack();
return 1;
}
如果不是动态库,可以这样导出全局模块 c_util:
int main()
{
...
LuaBinding(L).beginModule("c_util")
.addFunction("foo", []() { return 123; })
.endModule();
...
}
如果不想让它成为全局模块,则需要在 package.preload 表中注册一个加载函数.
Lua程序设计 第3版 英文版 programming in lua 3ed
The preload searcher allows the definition of an arbitrary function to load a module.
It uses a table, called package.preload, to map module names to loader functions.
When searching for a module name, this searcher simply looks for the given name in the table.
If it finds a function there, it returns this function as the module loader.
Otherwise, it returns nil.
This searcher provides a generic method to handle some non-conventional situations.
For instance, a C library statically linked to Lua can register its luaopen_ function into the preload table,
so that it will be called only when (and if) the user requires that module.
In this way, the program does not waste time opening the module if it is not used.
代码示例:
extern "C" int open_my_module(lua_State* L)
{
LuaRef mod = LuaRef::createTable(L);
LuaBinding(mod)
.addFunction("get_my_svr_id", &Util::GetMySvrId)
;
mod.pushToStack();
return 1;
}
int main()
{
...
LuaRef table(L, "package.preload");
table["c_util"] = LuaRef::createFunctionWith(L, open_my_module);
...
}
Lua 测试:
assert(c_util == nil)
local t = require("c_util")
assert("table" == type(t))
assert("function" == type(t.get_my_svr_id))