lua的一項重要用途就是作為一種配置語言(configuration language)。
目前,我們常用的配置文件格式有XML和ini, XML層次分明,但其缺點就是寫起來太繁雜,對一些關鍵字如<>之類的處理比較特殊。而ini呢,配置不夠靈活,只有簡單的段-
鍵-值模式,對於一些多層結構的配置,或者一些列表類型的配置,就顯得力不從心了,往往需要編碼人員自己分割字符串。
Lua腳本非常簡潔清晰,是非常適合做配置文件的,無論是映射表型配置,還是列表型配置,還是簡單的鍵值配置,lua都可以完全勝任。而且lua格式清新簡潔,一看就懂。
下面的代碼主要是讀變量和table。
mycon.lua
--my config width = 300 height = 400 luat_Test1={a=123, b=456, c=789} luat_Test2={123, 456, 789}
這里說個題外話,Lua不會根據一個范圍的值來創建表,而是根據設定的單個值來創建表內容,比如:
textTable = {} textTable[2000] = "hello 2000!"
這里雖然會生成許多未使用的Key,但不必擔心這個方法會犧牲任何表的存儲空間。
main.cpp
#include<stdio.h> //如不用extern會出現連接錯誤,編譯成了C++文件 extern "C" { #include "lua.h" #include "lauxlib.h" #include "lualib.h" } #pragma comment(lib, "lua5.1.lib") void ReadVariable (lua_State *L,int *width,int *height){ lua_getglobal(L,"width"); //獲得Lua中變量的值,將其放入棧中 lua_getglobal(L,"height"); if(!lua_isnumber(L,-2)) //棧頂為-1,然后依次減少 luaL_error(L,"`width' should be a number\n"); if(!lua_isnumber(L,-1)) luaL_error(L,"`height' should be a number\n"); *width = (int)lua_tonumber(L,-2); //將棧頂元素轉化為數字 *height = (int)lua_tonumber(L,-1); printf("width is %d ,height is %d\n\n",*width,*height); } static void ReadTableFromItem(lua_State *L, const char* lpszTableName, const char* lpszTableItem) { lua_getglobal(L, lpszTableName); lua_pushstring(L, lpszTableItem);//首先把元素的名字壓入棧頂 lua_gettable(L, -2);//值會放在棧頂,同時剛才壓入的元素名字被彈出 printf("%s.%s=%d\n", lpszTableName, lpszTableItem, (int)lua_tonumber(L, -1)); lua_pop(L, 2); } static void ReadTableFromIndex(lua_State *L, const char* lpszTableName, int index) { lua_getglobal(L, lpszTableName); lua_rawgeti(L, -1, index);//獲得第一個元素 printf("%s[%d]=%d\n", lpszTableName, index, (int)lua_tonumber(L, -1)); lua_pop(L, 2); } static void EnumTableItem(lua_State *L, const char* lpszTableName) { lua_getglobal(L, lpszTableName); int it = lua_gettop(L); lua_pushnil(L); printf("Enum %s:", lpszTableName); while(lua_next(L, it))//用lua_next可以遍歷這個數組 { printf(" %d", (int)lua_tonumber(L, -1)); lua_pop(L, 1); } printf("\n\n"); lua_pop(L, 1); } int main(int argc, char* argv[]) { if (argc != 2) { printf("param error!\n"); return 0; } char *filename = argv[1]; lua_State *L = lua_open(); luaL_openlibs(L); //新版本庫添加的方法 if(luaL_loadfile(L,filename) || lua_pcall(L,0,0,0)){ luaL_error(L,"loadfile error! %s \n",lua_tostring(L,-1)); } int w=1,h=2; ReadVariable(L,&w,&h); ReadTableFromItem(L, "luat_Test1", "a"); // 等價與lua代碼:print(luat_Test1.a) ReadTableFromItem(L, "luat_Test1", "b"); ReadTableFromItem(L, "luat_Test1", "c"); EnumTableItem(L, "luat_Test1"); // 枚舉Table ReadTableFromIndex(L, "luat_Test2", 1); // 等價與lua代碼:print(luat_Test1[1]) ReadTableFromIndex(L, "luat_Test2", 2); ReadTableFromIndex(L, "luat_Test2", 3); EnumTableItem(L, "luat_Test2"); getchar(); return 0; }
關於配置文件安全的問題,一般會將這些lua文件進行加密。
配置文件多數以excel轉lua的方式配置,網上也有很多相關工具。例如用xlrd