轻量级脚本语言,源代码也及其轻量,能很方便得嵌入到C/C++。
Lua最著名的的莫过于游戏脚本,但这次过程中新发现的Nginx+Lua,着实让我长见识了(难道只是自己孤陋寡闻TT)。
curl -R -O http://www.lua.org/ftp/lua-5.2.3.tar.gz
tar zxf lua-5.2.3.tar.gz
解压后,“doc/readme.html"详细介绍了Lua的编译与安装。
这里,如果选择自行配置编译的话,就是如下生成一个lib,两个exe:
library:
lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c
interpreter(解释器,可交互,运行Lua文本或预编译字节码):
library, lua.c
compiler(编译器,生成预编译二进制文件):
library, luac.c
但需要注意以下几点:
编译时,一般要定义如下些宏:
# Window
_WIN32
LUA_BUILD_AS_DLL
LUA_COMPAT_ALL
# Linux
LUA_USE_LINUX
LUA_COMPAT_ALL
另外,Linux上需要安装readline:
yum install readline readline-devel -y
并且链接时,需要添加:
-lm -Wl,-E -ldl -lreadline
然后,就可以愉快得玩耍了。
推荐官方书籍:Programming in Lua, Third Edition,书本示例可见附1。
或者这些资料:
如果对Lua源码感兴趣的话:
PiL第四部分介绍了Lua原生的C API,而Luabind则是Lua的C++封装了,其受Boost.Python所启发。
官方文档里只介绍了bjam来编译,自行配置编译的话,步骤如下:
Issue 1: compile luabind with errors
error C3861: 'lua_strlen': identifier not found
error C2065: 'LUA_GLOBALSINDEX' : undeclared identifier
Issue 2: incompatibility of luabind and boost on linux, here is the patch
.../luabind/detail/call_member.hpp:319:7: note: in expansion of macro 'BOOST_PP_ITERATION_FLAGS'
#elif BOOST_PP_ITERATION_FLAGS() == 1
.../luabind/detail/call_function.hpp:326:7: ...
.../luabind/wrapper_base.hpp:92:7: ...
内容其实挺多,最好阅读下官方文档。
以下是官方的Hello world,更多文档示例代码也请见附1。
lb_hello.cc
#include <iostream>
#include "luabind/luabind.hpp"
void greet() {
std::cout << "hello world!" << std::endl;
}
extern "C" SHARED_EXPORT
int luaopen_lbhello(lua_State *L) {
using namespace luabind;
// register the functions to create classes from Lua, and initialize
// some state-global structures used by luabind.
open(L);
// register all declared functions or classes in the global namespace
// in Lua.
module(L)
[
def("greet", &greet)
];
return 0;
}
编译动态库时,SHARED_EXPORT在Windows下得是__declspec(dllexport),Linux则不需要。
lb_hello.lua
require "lbhello"
-- package.loadlib('lbhello.dll', "luaopen_lbhello")()
greet()
写Luabind示例时,遇到的以下情况值得留意:
另外,官方文档到17节才提到了Build options。18节是Implementation notes,简单规避方式为:不以__luabind为变量前缀,不覆盖全局super。
Lua即时编译器,将Lua脚本编译成本地机器码来运行,提升效率。
官方Installation里已有详细说明。不过目前版本仅完全兼容5.1。5.2的话,Extensions from Lua 5.2内有描述,定义宏DLUAJIT_ENABLE_LUA52COMPAT能开启更多些特性。
cd LuaJIT-2.0.3
# Linux
make PREFIX=/usr/local/lj-2.0.3
sudo make install PREFIX=/usr/local/lj-2.0.3
ln -s /usr/local/lj-2.0.3/bin/luajit /usr/bin/luajit
# luajit,确认可运行
# Windows
# "Visual Studio Command Prompt"
cd src
msvcbuild
# 拷贝src目录下的luajit.exe,lua51.dll以及jit目录即可使用
# 忘记jit目录的话,会遇到Issue 1
# luajit.exe,确认可运行
Issue 1: luajit.exe: unknown luaJIT command or jit.* modules not installed
如果自行配置编译的话,可以参考这个:
同样看官方Running LuaJIT的说明,用如下代码试用比较了下:
test.lua
local os = require "os"
local string = require "string"
local debug = require "debug"
function timeit(func, ...)
fname = debug.getinfo(1, "n").name
begstamp = os.time()
result = func(...)
endstamp = os.time()
elapsed = os.difftime(endstamp, begstamp)
print(string.format("%s cost time: %.2f", fname, elapsed))
return result
end
function hanoi(n, a, b, c)
if n == 1 then
print("Move "..n.." from "..a.." to "..c)
else
hanoi(n-1, a, c, b)
print("Move "..n.." from "..a.." to "..c)
hanoi(n-1, b, a, c)
end
end
timeit(hanoi, 15, "A", "B", "C")
然后:
# 字节码
luac -o test.out test.lua
lua test.out
# 机器码
luajit -b test.lua test.out
luajit test.out
结果:15的话,1.00;改到20的话,也差不多都38.00。PC上上述代码测不出什么差距啊==。
Nginx嵌入Lua作脚本。
本文主要介绍了Lua的一些环境。针对学习的话,仅给出了参考资料以及整理的示例(见附1)。
对于Lua的话,个人感受很不错。可能是因为自己以前没做过类似的实践,譬如把V8或Python嵌入C++作为脚本。也充分体现了Lua良好的可嵌入性。
总之,感兴趣的话,还不赶紧动起手来。
下载:lua_start.zip。
C::B工程,目录树如下:
lua_start/
├─build/
│ ├─lua_start-gcc.cbp # for gnu gcc
│ └─lua_start-msvc.cbp # for msvc 2010
├─src/
│ ├─Luabind/ # Luabind文档示例
│ └─PiL3/ # PiL3书籍示例
├─third_party/
│ ├─boost_1_55_0/
│ ├─lua-5.2.3/
│ ├─luabind-0.9/
│ └─luasocket-3.0-rc1/
└─tools/
third_party/下都是空目录,前文已提及下载。目录名不能变,版本最好一致。
其中LuaSocket在PiL3第9章协程会用到,请下载这个LuaSocket 3.0-rc1。
另外,Linux下也将lua编译成了动态库,并会在post build时拷贝到/usr/local/lib/目录。所以,最好以root用户打开C::B,以确保有操作权限。
ll /usr/local/lib/liblua*
PiL3/下可以在当前目录,通过lua.bat,lua.sh或lua.py来运行书籍示例脚本。
而Luabind/下只有lb_run.py,编译工程all_lua,all_luabind两个target后,直接"python lb_run.py"就会运行所有例子了。