??xml version="1.0" encoding="utf-8" standalone="yes"?>
在《数?span lang="EN-US">/配置 的存储方?span lang="EN-US"> Json??span lang="EN-US">JsonCpp库用ؓ例》《数?span lang="EN-US">/配置 的存储方?span lang="EN-US"> Json??span lang="EN-US">Cocos2D For Iphone+TouchJsonZ 》中我ȝ了一下怎么使用Json作ؓ配置Q但是,其实Json虽然语法格式单,同时解析库的使用也非常简单,但是Q因U简单性,~少有的时候的非帔R要的功能。比如配|文件中对另一行配|的引用Q比如配|段的承等Q这些可以?span lang="EN-US">XML来解冻I另外Q有的时候还会需要在配置文g中进行简单的q算Q比如我常怼有想某个图片羃攑ֈ目前分L率的几分之几q样的需求,此时Q用一个完整的可以q行q算的语a来做配置的诱惑实在太大了。。。。。?span lang="EN-US">
Lua是为此而生的。。。。。。虽然现?span lang="EN-US">Lua的功能已l远q不止这样了Q但是最初设?span lang="EN-US">Lua的目的就是一个简单的配置语言。见Lua的历?。虽然其实用Python作ؓ配置也完全可行,但是Lua有着速度快的优点Q而且Q?span lang="EN-US">Lua实在?span lang="EN-US">Python太多了Q很适合嵌入到程序中厅R?span lang="EN-US">
对于使用Lua作ؓ配置Q事实上q当于?span lang="EN-US">C++中嵌?span lang="EN-US">LuaQ只不过不用其脚本语a的一些复杂特性,仅仅其作ؓ一个配|文件来看?span lang="EN-US">
q里q是以原来《数?span lang="EN-US">/配置 的存储方?span lang="EN-US"> Json??span lang="EN-US">JsonCpp库用ؓ例》文中开始的SDL工程作ؓ例子?span lang="EN-US">
首先搭徏可以内嵌使用Lua?span lang="EN-US">C++~译环境Q下载一?span lang="EN-US">luabinaries 是简单的办法Q现在我使用的是lua5_1_4_Win32_dll8_lib.zip 。这里我甚至不需要一个可以运行的Lua交互环境。。。。?span lang="EN-US">
单示?span lang="EN-US">
首先建立一个简单的Lua文g,命名?span lang="EN-US">picture.lua
name="dragon.png"
rotation=180
虽然只有单的两行Q也是个合法?span lang="EN-US">LuaE序?span lang="EN-US">
然后?span lang="EN-US">C++E序中读取出来,q个q程实际上是使用?span lang="EN-US">Lua?span lang="EN-US">C APIQ具体的Lua?span lang="EN-US">C APIq里׃详细讲解了,那比较复杂,可以参考?span lang="EN-US">Programming in Lua》,中文版也已经有了。这里仅仅作Z个例子提供参考吧?span lang="EN-US">
现在可以开始完?span lang="EN-US">C++的程序了Q?span lang="EN-US">
首先Q包含必要的头文Ӟ
extern "C" {
#include "lua/lua.h"
#include "lua/lauxlib.h"
#include "lua/lualib.h"
}
因ؓlua的头文g完全是只考虑C语言的情况,所以在C++中用的时候需要自己添?span lang="EN-US">extern "C"。这是典型的?span lang="EN-US">C++不屑的态度Q因为现在大部分的纯C语言写的库,都会很自然的通过宏判断来自动使用extern "C"语句?span lang="EN-US">
然后Q?span lang="EN-US">
using namespace std;
struct PictureInfo {
string name;
float rotation;
}gPictureInfo;
void PictureInit() {
lua_State *L = luaL_newstate();
if ( luaL_dofile(L, "picture.lua" ) != 0 ) {
printf("Error happen." );
// handle the error.
exit(1 );
}
lua_getglobal(L, "name" );
assert(lua_isstring(L, -1 ) == 1 );
gPictureInfo.name = lua_tostring(L, -1 );
lua_getglobal(L, "rotation" );
gPictureInfo.rotation = (float )lua_tonumber(L, -1 );
lua_close(L);
}
q里我们使用的所有变量全部都?span lang="EN-US">global的变量,所以调用v来非常方ѝ上面的主要内容是?span lang="EN-US">Lua C API的用,׃其本w较为复杂,q里一下也讲不清楚?span lang="EN-US">
基本程是创建新?span lang="EN-US">Lua state,然后?span lang="EN-US">luaL_dofile 执行我们需要的配置文gQ然后调?span lang="EN-US">lua_getglobal 加适当的{换来获取我们需要的配置倹{这里的例子是一个字W串和一个QҎ?span lang="EN-US">
具体昄的效果和其他代码参考《数?span lang="EN-US">/配置 的存储方?span lang="EN-US"> Json??span lang="EN-US">JsonCpp库用ؓ例》就好了Q这里不重复描述了?span lang="EN-US">
数组
?span lang="EN-US">Lua中数l也通过table的Ş式来表示Q这里我仅仅介绍怎么?span lang="EN-US">lua文g中获取配|,具体的显C等东西也不再篏qC?span lang="EN-US">
q里Q我们徏立一个包含数l的lua文g作ؓ配置Q?span lang="EN-US">
data = {
{ name="dragon.png" , rotation=180 } ,
{ name="dragon.png" , rotation=0 }
}
下面看怎么配|读取出来:
using namespace std;
struct PictureInfo {
string name;
float rotation;
};
vector gPictureInfoVec;
void PictureInit() {
lua_State *L = luaL_newstate();
if ( luaL_dofile(L, "picture.lua" ) != 0 ) {
printf("Error happen." );
// handle the error.
exit(1 );
}
// get the table
lua_getglobal(L, "data" );
assert(lua_istable(L, -1 ) == 1 );
/* table is in the stack at index 't' */
lua_pushnil(L); /* first key */
while (lua_next(L, -2 ) != 0 ) {
PictureInfo info;
/* 'key' (at index -2) and 'value' (at index -1) */
// push the key to stack for getting the value
lua_pushstring(L, "name" );
// now the table is in the -2 and key in the top(-1)
lua_gettable(L, -2 );
assert(lua_isstring(L, -1 ));
info.name = lua_tostring(L, -1 );
lua_pop(L, 1 );
// push the key to stack for getting the value
lua_pushstring(L, "rotation" );
// now the table is in the -2 and key in the top(-1)
lua_gettable(L, -2 );
assert(lua_isnumber(L, -1 ));
info.rotation = lua_tonumber(L, -1 );
gPictureInfoVec.push_back(info);
/* removes the key we pushed and the 'value' of the global table ; keeps 'key' for next iteration */
lua_pop(L, 2 );
}
lua_close(L);
}
代码中的注释解释的已l够详细了,但是因ؓLua ?span lang="EN-US">API的确不是太容易理解,q里也无法一下讲清楚Q所以还是先了解Lua ?span lang="EN-US"> API为好Q具体的API的意义可以参考参考手册?span lang="EN-US">
上面仅仅使用?span lang="EN-US">Lua API遍历数组以及?span lang="EN-US">table中获取元素的Ҏ?span lang="EN-US">
假如仅仅只有上面q些Q是看不出用lua作ؓ配置的好处的Q用lua做配|的好处在于可以利用lua的特性实现配|段之间的承以及完整的q算功能?span lang="EN-US">
比如_完全不用修改上面的读取配|的代码Q我们仅仅修攚w|,看看?span lang="EN-US">Lua中用上q功能:
data1 = { name="dragon.png" , rotation=180 }
data2 = { name = data1.name, rotation = data1.rotation / 2 }
data = {
data1, data2
}
此时Q?span lang="EN-US">data2的数据完全依赖于data1的数据,当有M东西需要修改的时候,你只需要修改一个地方,对于配置来说Q?span lang="EN-US">don't repeat yourself也是很有意义的。最最重要的的是,在配|中能够q行计算那是非常强大Q即使完全不?span lang="EN-US">lua的函数功能与代码的交互,仅仅通过lua的计,也可以完成游戏中所?span lang="EN-US">sprite的布局。。。。。?span lang="EN-US">
结
相对于?span lang="EN-US">XML,JsonQ?span lang="EN-US">Lua作ؓ配置l对是最最强大的。。。。。。作Z个完整的语言Q它拥有你想在配|中实现的一切功能。但是缺点也是很明显的:
首先Q速度上,Lua需要解释运行,可能明显跟不?span lang="EN-US">XML或?span lang="EN-US">Json的解析速度。但是,配置的解析读取可以都攑֜初始化阶D,所以配|不是太多的时候,也不太q难以接受,另外Q还可以?span lang="EN-US">lua的配|完全作为开发期的一U机制用,在发布后完全转化?span lang="EN-US">2q制数据?span lang="EN-US">
其次Q?span lang="EN-US">Lua的配|读取需要手动调?span lang="EN-US">Lua?span lang="EN-US">API来完成,相对?span lang="EN-US">XMLQ?span lang="EN-US">Json那种有很方便的库的情况,使用上还是麻烦一些,特别?span lang="EN-US">Lua?span lang="EN-US">API的用ƈ不是那么单易懂,不算太直观。但是,q也不是不可以克服的Q完全可以自己写个小型的库将Lua?span lang="EN-US">API装hQŞ成一个类?span lang="EN-US">JsonCpp那样的库Q用Map来表CZ切。这个可能需要限制一?span lang="EN-US">Lua语法的时候,或者在解析的时候进行取舍,比如函数啥的可能需要过滤掉Q不焉׃太像?span lang="EN-US">Lua作ؓ配置使用了?span lang="EN-US">
q有Q?span lang="EN-US">Lua的配|的生成更加是没?span lang="EN-US">XML,Json那样有完善库支持来的方便Q这Ҏ时没有办法克服,写一个自动生?span lang="EN-US">Lua配置文g的库感觉q不是太q容易的事情。而且Q自动生成时Q?span lang="EN-US">lua的优势其实ƈ没有余地发挥出来Q那L话,q不如?span lang="EN-US">Json?span lang="EN-US">
ȝ来说Q假如是没有工具Q需要大量手写配|的话,?span lang="EN-US">Lua?span lang="EN-US">APIq行一层简单的装Q然后?span lang="EN-US">Lua来做配置Q那q是件很爽的事情Q需要手写的时候,你才会感觉到一个完整语a作ؓ配置l你带来的好处?span lang="EN-US">
本文来自CSDN博客Q{载请标明出处Q?span lang="EN-US">http://blog.csdn.net/vagrxie/archive/
http://blog.csdn.net/bhwst/archive/2010/07/29/5774746.aspx
VC要编译LUA文g必须先配|VC~程环境。。我用的是VC6.0Qlua 5.1.4?
首先lua?lua.h" Q?lualib.h"Q?"lauxlib.h" q三个放在vcE序include文g夹下
然后lua的lua5.1.lib攑֜lib文g夹下OK?
下面看看我写的一个小例子Q?
a.cpp
view plaincopy to clipboardprint?
#include "windows.h"
extern "C"{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
#pragma comment(lib,"lua5.1.lib")
lua_State * L;
static int clib(lua_State *L) //llua调用的c函数必须定义成static int XXX(lua_State *L)
{
char path[MAX_PATH];
GetCurrentDirectory(MAX_PATH,path);
lua_pushstring(L,path);
return 1; //Z么要q回1Q这是有依据的,该函数把l果压入了栈Qlua调用该函数将从栈?
//?个结?
}
int main ( int argc, char *argv[] )
{
int sum;
//创徏一个指向lua解释器的指针
L = luaL_newstate();
//加蝲lua标准?
luaL_openlibs(L);
//注册C++函数
lua_register(L,"clib",clib);
//加蝲脚本
luaL_dofile(L,"4.lua");
//调用函数
lua_getglobal(L,"run");
//q行函数q把l果压入?
lua_pcall(L,0,0,0);
//关闭q放资?
lua_close(L);
return 0;
}
#include "windows.h"
extern "C"{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
#pragma comment(lib,"lua5.1.lib")
lua_State * L;
static int clib(lua_State *L) //llua调用的c函数必须定义成static int XXX(lua_State *L)
{
char path[MAX_PATH];
GetCurrentDirectory(MAX_PATH,path);
lua_pushstring(L,path);
return 1; //Z么要q回1Q这是有依据的,该函数把l果压入了栈Qlua调用该函数将从栈?
//?个结?
}
int main ( int argc, char *argv[] )
{
int sum;
//创徏一个指向lua解释器的指针
L = luaL_newstate();
//加蝲lua标准?
luaL_openlibs(L);
//注册C++函数
lua_register(L,"clib",clib);
//加蝲脚本
luaL_dofile(L,"4.lua");
//调用函数
lua_getglobal(L,"run");
//q行函数q把l果压入?
lua_pcall(L,0,0,0);
//关闭q放资?
lua_close(L);
return 0;
}
4.lua文g
view plaincopy to clipboardprint?
function run()
print("call running from c")
print(clib())
end
function run()
print("call running from c")
print(clib())
end
q个例子实现了C与lua的相互调用。。另外,q可以把我前面一lua调用C dll的内Ҏ合在一赗?
本文来自CSDN博客Q{载请标明出处Qhttp://blog.csdn.net/bhwst/archive/2010/07/29/5774746.aspx
Alas, Windows does not like an extra dot in there. Many things
break when you have an extra dot in DLL names. Depends on the
version of the OS, on the specific system call, on the library or
tool used ... it's hopeless. So please let's forget about it.
--Mike
来自lua-users.org的一个帖??br>原来?q前有h定了一个lua51.dll名字的动态库Qƈ且,有h觉得我们非常需要在5?之间加一个点Q不然lua?.1版岂不是看成lua?1版了Q?br>ҎQ有一步提Z疑问 Q认个问题怎么q么久了竟然没有Z复?
接着有h回答了:
But who's duty is to resolve the issue?
It's clearly not an issue of Lua as a language. It's just a consequence of (a very popular) LuaBinaries once releasing lua5.1.dll that became a de facto binary standard, then authors of many third-party Lua libraries were releasing binary packages compatible with LuaBinaries.
Note: I'm not blaming LuaBinaries; that was just one unfortunate decision that is difficult to be undone. --
Shmuel
我们知道了:
LuaBinaries做出了一个错误的军_Q但是已l发布了Q很多第3方的库也发布了,q且依赖于LuaBinaries的这个lua51.dllQ于是:
that was just one unfortunate decision that is difficult to be undone.
那仅仅是一个过d下,现在难以撤销的不q决定。。。。。。。。。。。?
有的东西存在了,即是不合理的存在,因ؓ它存在了一D|间了Q因为惯性,它还会存在在那里。编E中Q这U情늻常出现。突然让我想起上个项目中Q大家经常对目中蹩脚代码存在原因的解释Q?#8220;历史原因”?br> 对于代码来说Q即使大安知道可以重构Q但是重构是有代LQ很多时候大家就妥协在历史原因当中?br> 对于语言来说QC++是对历史进行最大妥协而生的语言Q大安承认Q假如当qC++不兼容C的话QC++Ҏ得不到现在q样的流行程度,也都承认Q因为C++兼容CQ(常常被称为历史的包袱QC++在语a的优程度上损失了太多?br> 惌v国内某个大牛有过cM的感慨,“现在每做一个设计决定的时候都非常心Q因为那可能会被使用非常非常长的旉Q当它还能正常工作的时候,甚至不会有h惌去重写它“
呵呵Q仅仅将q个有趣的事件作为编E中的一个轶事来看吧?
本文来自CSDN博客Q{载请标明出处Qhttp://blog.csdn.net/vagrxie/archive/2010/07/23/5756804.aspx