将 Lua 源代码直接放入最终产品,显然不是个理想选择。利用 LOOP 提供的 Precompiler 工具,可以将 Lua 模块编译为 C 代码。
准备工作
LOOP 是一个 Lua 的 OOP 框架,Precompiler 则是 LOOP 中包含的一个工具。要安装 LOOP,得先安装 LuaRocks。
$ wget http://luarocks.org/releases/luarocks-2.0.5.tar.gz $ tar zxf luarocks-2.0.5.tar.gz $ cd luarocks-2.0.5 $ ./configure $ make $ sudo make install
然后安装 LOOP:
$ sudo luarocks install loop
OK,现在准备工作完成了,接下来就是编译 Lua 模块为 C 代码。
编译
我们的框架中有一个 display.lua 模块,下面的代码可以将这个模块编译出来:
$ precompiler.lua -o luaqeeplayscripts -l "?.lua" -b -p qeeplay qeeplay/display.lua
最后会得到 luaqeeplayscripts.c/.h 文件。其中定义了函数:
qeeplay int luaopen_qeeplay_display(lua_State *L);
在上述命令行中,各个参数的意义如下:
-o: 指定输出文件名,例如 -o luaqeeplayscripts 会输出 luaqeeplayscripts.c/.h -l: 指定推断 lua 模块名的模式,设定为 -l "?.lua" 就会以 lua 源文件名称作为模块名。 例如 display.lua 就是 display 模块。如果 display.lua 文件在 qeeplay 子目录中, 那么 qeeplay/display.lua 的模块名就是 qeeplay.display。 -b: 编译为字节码 -p: 函数定义的前缀,一般指定一个可以方便以后对生成的 .c/.h 文件进行再处理
如果要将多个 lua 文件编译为一个 C 代码,可以添加更多的文件名到命令行中,例如:
$ precompiler.lua -o luasocketscripts -l "?.lua" -b -p socket \ socket.lua \ socket/url.lua \ socket/tp.lua \ socket/smtp.lua \ socket/mime.lua \ socket/ltn12.lua \ socket/http.lua \ socket/ftp.lua
会创建 luasocketscripts.c/.h 文件,其中定义下列函数:
socket int luaopen_socket(lua_State *L); socket int luaopen_socket_url(lua_State *L); socket int luaopen_socket_tp(lua_State *L); socket int luaopen_socket_smtp(lua_State *L); socket int luaopen_socket_mime(lua_State *L); socket int luaopen_socket_ltn12(lua_State *L); socket int luaopen_socket_http(lua_State *L); socket int luaopen_socket_ftp(lua_State *L);
载入编译好的 C 代码
利用前一篇文章中的 lualoadexts.c/lualoadexts.h,做一些修改即可:
luaqeeplayscripts.c
#include "lualoadexts.h" // qeeplay #include "luaqeeplayscripts.h" static luaL_Reg luax_preload_list[] = { {"qeeplay.display", luaopen_qeeplay_display}, {NULL, NULL} }; void luax_initpreload(lua_State *L) { .... }
如果有更多模块需要载入,只需要 include 相应的头文件,并修改 luax_preload_list 定义即可。