前言
在《數據/配置 的存儲方式 Json篇 以JsonCpp庫使用為例》《數據/配置 的存儲方式 Json篇 以Cocos2D For Iphone+TouchJson為例 》中我總結了一下怎么使用Json作為配置,但是,其實Json雖然語法格式簡單,同時解析庫的使用也非常簡單,但是,因為這種簡單性,缺少有的時候的確非常需要的功能。比如配置文件中對另一行配置的引用,比如配置段的繼承等,這些可以使用XML來解決,另外,有的時候還會需要在配置文件中進行簡單的運算,比如我就常常會有想將某個圖片縮放到目前分辨率的幾分之幾這樣的需求,此時,用一個完整的可以進行運算的語言來做配置的誘惑實在太大了。。。。。。
Lua就是為此而生的。。。。。。雖然現在Lua的功能已經遠遠不止這樣了,但是最初設計Lua的目的就是一個簡單的配置語言。見Lua的歷史 。雖然其實用Python作為配置也完全可行,但是Lua有著速度快的優點,而且,Lua實在比Python小太多了,很適合嵌入到程序中去。
對于使用Lua作為配置,事實上就相當于在C++中嵌入Lua,只不過不用其腳本語言的一些復雜特性,僅僅將其作為一個配置文件來看。
這里還是以原來《數據/配置 的存儲方式 Json篇 以JsonCpp庫使用為例》文中開始的SDL工程作為例子。
首先搭建可以內嵌使用Lua的C++編譯環境,下載一個luabinaries 是簡單的辦法,現在我使用的是lua5_1_4_Win32_dll8_lib.zip 。這里我甚至不需要一個可以運行的Lua交互環境。。。。。
簡單示例
首先建立一個簡單的Lua文件,命名為picture.lua
name="dragon.png"
rotation=180
雖然只有簡單的兩行,也是個合法的Lua程序。
然后在C++程序中讀取出來,這個過程實際上是使用了Lua的C API,具體的Lua的C API這里就不詳細講解了,那比較復雜,可以參考《Programming in Lua》,中文版也已經有了。這里僅僅作為一個例子提供參考吧。
現在可以開始完成C++的程序了:
首先,包含必要的頭文件:
extern "C" {
#include "lua/lua.h"
#include "lua/lauxlib.h"
#include "lua/lualib.h"
}
因為lua的頭文件完全是只考慮C語言的情況,所以在C++中使用的時候需要自己添加extern "C"。這是典型的對C++不屑的態度,因為現在大部分的純C語言寫的庫,都會很自然的通過宏判斷來自動使用extern "C"語句。
然后:
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);
}
這里我們使用的所有變量全部都是global的變量,所以調用起來非常方便。上面的主要內容就是對Lua C API的使用,由于其本身較為復雜,這里一下也講不清楚。
基本流程是創建新的Lua state,然后用luaL_dofile 執行我們需要的配置文件,然后調用lua_getglobal 加適當的轉換來獲取我們需要的配置值。這里的例子是一個字符串和一個浮點數。
具體顯示的效果和其他代碼參考《數據/配置 的存儲方式 Json篇 以JsonCpp庫使用為例》就好了,這里不重復描述了。
數組
在Lua中數組也通過table的形式來表示,這里我僅僅介紹怎么從lua文件中獲取配置,具體的顯示等東西也不再累述了。
這里,我們建立一個包含數組的lua文件作為配置:
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);
}
代碼中的注釋解釋的已經夠詳細了,但是因為Lua 的API的確不是太容易理解,這里也無法一下講清楚,所以還是先了解Lua 的 API為好,具體的API的意義可以參考參考手冊。
上面僅僅使用了Lua API遍歷數組以及從table中獲取元素的方法。
假如僅僅只有上面這些,是看不出用lua作為配置的好處的,用lua做配置的好處在于可以利用lua的特性實現配置段之間的繼承以及完整的運算功能。
比如說,完全不用修改上面的讀取配置的代碼,我們僅僅修改配置,看看在Lua中使用上述功能:
data1 = { name="dragon.png" , rotation=180 }
data2 = { name = data1.name, rotation = data1.rotation / 2 }
data = {
data1, data2
}
此時,data2的數據完全依賴于data1的數據,當有任何東西需要修改的時候,你只需要修改一個地方,對于配置來說,don't repeat yourself也是很有意義的。最最重要的的是,在配置中能夠進行計算那是非常強大,即使完全不用lua的函數功能與代碼的交互,僅僅通過lua的計算,也可以完成游戲中所有sprite的布局。。。。。。
小結
相對于使用XML,Json,使用Lua作為配置絕對是最最強大的。。。。。。作為一個完整的語言,它擁有你想在配置中實現的一切功能。但是缺點也是很明顯的:
首先,速度上,Lua需要解釋運行,可能明顯跟不上XML或者Json的解析速度。但是,配置的解析讀取可以都放在初始化階段,所以配置不是太多的時候,也不算太過難以接受,另外,還可以將lua的配置完全作為開發期的一種機制使用,在發布后完全轉化為2進制數據。
其次,Lua的配置讀取需要手動調用Lua的API來完成,相對于XML,Json那種有很方便的庫的情況,使用上還是麻煩一些,特別是Lua的API的使用并不是那么簡單易懂,不算太直觀。但是,這也不是不可以克服的,完全可以自己寫個小型的庫將Lua的API封裝起來,形成一個類似JsonCpp那樣的庫,用Map來表示一切。這個可能需要限制一些Lua語法的時候,或者在解析的時候進行取舍,比如函數啥的可能需要過濾掉,不然那就不太像將Lua作為配置使用了。
還有,Lua的配置的生成更加是沒有XML,Json那樣有完善庫支持來的方便,這點暫時沒有辦法克服,寫一個自動生成Lua配置文件的庫感覺并不是太過容易的事情。而且,自動生成時,lua的優勢其實并沒有余地發揮出來,那樣的話,還不如使用Json。
總的來說,假如是沒有工具,需要大量手寫配置的話,對Lua的API進行一層簡單的封裝,然后使用Lua來做配置,那還是件很爽的事情,需要手寫的時候,你才會感覺到一個完整語言作為配置給你帶來的好處。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/vagrxie/archive/2010/07/23/5758521.aspx