C++轻量级脚本:lua
2014-04-22 21:56
561 查看
C++轻量级脚本:lua
1) Lua
轻量级脚本语言,源代码也及其轻量,能很方便得嵌入到C/C++。Lua最著名的的莫过于游戏脚本,但这次过程中新发现的Nginx+Lua,着实让我长见识了(难道只是自己孤陋寡闻TT)。
2) 准备
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的编译与安装。
2.1) 编译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
但需要注意以下几点:
"src/luaconf.h"内可自定义特性,并能查看到其对一些宏定义的说明。
编译"compiler"时,链接"library"动态库有问题的话,就直接链接lib所有的object文件吧。
编译时,一般要定义如下些宏:
# 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
然后,就可以愉快得玩耍了。
2.2) 学习Lua
推荐官方书籍:Programming in Lua, Third Edition,书本示例可见附1。或者这些资料:
Learn Lua in 15 Minutes
Lua简明教程
Lua游戏开发实践指南
如果对Lua源码感兴趣的话:
Lua源码欣赏
Lua代码分析
3) Luabind
PiL第四部分介绍了Lua原生的C API,而Luabind则是Lua的C++封装了,其受Boost.Python所启发。官方文档里只介绍了bjam来编译,自行配置编译的话,步骤如下:
下载Luabind与Boost。注意:如果是Lua5.2的话,那么下这个Luabind。不然,会遇到Issue 1。
添加Luabind/src下所有文件,包含Luabind、Boost根目录及Lua/src目录,链接Lua库,添加宏"LUABIND_DYNAMIC_LINK",然后编译即可。
Linux下可能会遇到luabind与boost不兼容,在宏"BOOST_PP_ITERATION_FLAGS"位置。问题及补丁见Issue 2。
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: ...
3.1) 使用Luabind
内容其实挺多,最好阅读下官方文档。以下是官方的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示例时,遇到的以下情况值得留意:
Window与Linux绑定Class时成员变量默认值不一致。可见附1"src/Luabind/lb_bind.*"。
基础类型成员变量默认值:Linux正常原值;Window上却是function。
非基础类型成员变量默认值:Linux正常引用,直接print()时tostring会出错,应该设个__tostring方法就好;Window上仍是function。
Window上用property()也一样,初次get也是function。仅当设了值后,再使用才正常。
另外,官方文档到17节才提到了Build options。18节是Implementation notes,简单规避方式为:不以__luabind为变量前缀,不覆盖全局super。
4) LuaJIT
Lua即时编译器,将Lua脚本编译成本地机器码来运行,提升效率。4.1) 编译LuaJIT
官方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
如果自行配置编译的话,可以参考这个:
使用VS IDE编译Luajit脚本引擎
4.2) 使用LuaJIT
同样看官方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上上述代码测不出什么差距啊==。
5) 其他
5.1) LDoc
使用LDoc给Lua生成文档5.2) ngx_lua
Nginx嵌入Lua作脚本。Nginx与Lua
Ngx_lua使用技巧和应用的范例
5.3) cloudwu@github
ejoy2d:2D图形引擎skynet:游戏服务器
6) 总结
本文主要介绍了Lua的一些环境。针对学习的话,仅给出了参考资料以及整理的示例(见附1)。对于Lua的话,个人感受很不错。可能是因为自己以前没做过类似的实践,譬如把V8或Python嵌入C++作为脚本。也充分体现了Lua良好的可嵌入性。
总之,感兴趣的话,还不赶紧动起手来。
附1:样例工程lua_start
下载: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"就会运行所有例子了。
相关文章推荐
- 关于指针的一些事情
- C/C++数据对齐详细解析
- C++中引用的使用总结
- C与C++之间相互调用实例方法讲解
- C++中引用(&)的用法与应用实例分析
- 解析C++ 浮点数的格式化输出
- 深入分析C++中几个最不常用的关键字
- c++中inline的用法分析
- C++ Primer 第一部分基本语言
- 深入解析C++ Data Member内存布局
- 从汇编看c++中默认构造函数的使用分析
- 关于C++中的友元函数的一些总结
- C++的sstream标准库详细介绍
- 基于C++自动化编译工具的使用详解
- 浅谈C++中的string 类型占几个字节
- C/C++ 宏详细解析
- 深入分析C++中两个大数相乘结果不正确的问题
- 探讨C++中数组名与指针的用法比较分析
- 深入解析C++中的引用类型
- C++可变参数的实现方法