《Programming in Lua 3》讀書筆記(二十二)

來源:互聯網
上載者:User

標籤:lua   讀書筆記   

日期:2014.8.6PartⅣ The C API
26 Extending Your Application     使用Lua很重要的一點是用來做配置語言。配合主語言做一些功能的配置。
 26.1 The Basics     有的時候程式需要配置一些功能資訊,很多時候可能有許多別的方法比用lua做配置要更簡單:如使用環境變數或者讀取檔案,讀取檔案涉及到檔案的解析。如果使用Lua進行配置的話,相當於用lua檔案替代了要讀取的如csv、txt檔案等。     使用Lua進行配置的時候,就需要使用Lua API去控制Lua來解析檔案了,然後從Lua的全域變數中得到要配置的值。Load函數承擔了負載檔案的功能,函數調用luaL_loadfile從給定名字的檔案中讀取語句快,然後調用lua_pcall來運行語句快。假如遇到了錯誤(例如:設定檔中的語法錯誤),此時函數將錯誤資訊push至棧中然後返回一個非零的錯誤碼;此時我們的程式使用lua_tostring 帶參數index -1 從棧頂得到資訊。e.g.lua_tostring(L,-1)     --從棧頂得到資訊     載入完檔案之後,就需要從Lua的全域變數中得到變數值了。此時調用lua_getglobal得到需要的值,參數為全域變數的名字。每一次調用都會將找到的全域變數值push值棧中,然後相應的主程式就從棧中得到相應的值。然後使用lua_is* 來確定值的類型,然後調用lua_to* 得到相應類型的值。     使用Lua做配置的好處就是,Lua幫你做了所有的文法檢測處理,(設定檔中甚至可以有注釋?);使用者可以用Lua來做更為複雜的配置處理,如設定檔可以提示使用者一些資訊,或者檢測某個環境變數來選擇合適的值:
e.g.--configuration fileif getenv("DISPLAY") == ":0.0" then     width = 300;height = 300else     width = 200;height = 200
     另外一個原因便是:現在來看很容易使用Lua給程式添加新的配置資訊,這個特性使得程式更為靈活。
 26.2 Table Manipulation     假設一個這樣的情境:需要配置視窗的背景顏色。此時需要有三個值:RGB值。通常在C中,每個值的範圍是[0,255],而Lua中,因為所有的number都是實數,所以使用的是[0,1]這個範圍。     通常為每一個值聲明一個變數會帶來很多麻煩,如:假如程式需要多種配置,如前景色彩、按鈕顏色等等,那這樣會需要很多的變數;而且這種方法不適合用預定義顏色,或者說預設值。此時,Lua中的table就適合做這樣的配置工作了:
e.g.background = {r = 0.30,g = 0.10,b = 0}
     使用table將會給指令碼帶來非常大的便利性;此時也可以方便的使用一些預定值了,如:
e.g.BLUE = { r = 0, g = 0, b = 1.0}background = BLUE
     而C代碼中要獲得這些值,可以如下來實現:
e.g.lua_getglobal(L,"background")if (! lua_istable(L,-1))     error(L,"'background' is not a table");red = getcolorfield(L,"r");green = getcolorfield(L,"g");blue = getcolorfield(L,"b");#define MAX_COLOR     255int getcolorfield(lua_State *L,const char* key){      int result;     //key 推出,而把相應的value推進棧    lua_pushstring(L,key);      lua_gettable(L,-2);     //前面兩段可以用 lua_getfield(L,-1,key);來替代     if(!lua_isnumber(L,-1))          error(L,"invalid component in background color");     result = (int)(lua_tonumber(L,-1)) * MAX_COLOR);     lua_pop(L,1);     return result;}
 
26.3 Calling Lua Function     設定檔可以定義函數給程式調用,這是Lua的一大強勢所在。     API調用一個函數是比較簡單的:首先,將要調用的函數push至棧中;接著將要調用的參數push至棧中;然後可以使用lua_pcall 函數執行實際的函數調用;最後從棧中得到調用的結果。     lua_pcall 的第二個參數表示的是傳遞參數的數量和返回結果的數量;第四個參數指的是錯誤處理函數,0表示沒有錯誤處理函數,其餘的值表示函數在棧中的位置index,因此這些函數首先應該push至棧中的;Lua將會根據實際的函數的運算結果來調整參數和返回的數量,如果需要將會push ni或者拋棄額外的值。在將結果push之前,lua_pcall 將會從棧中移除掉函數和函數的參數。當函數返回了多個結果,第一個結果將首先被push。     如果在lua_pcall運行過程中遇到了任何的錯誤,lua_pcall將會返回一個錯誤碼;不僅如此,還會將錯誤資訊push至stack中(並且仍然會推出函數和函數的參數)。在push錯誤資訊之前,如果有錯誤處理函數,lua_pcall還是會首先執行錯誤處理函數的。     而普通的錯誤情況下,lua_pcall 返回的是 LUA_ERRUN.有兩類錯誤將會返回不同的錯誤碼:第一種情況是記憶體配置錯誤,將會返回LUA_ERRMEM;第二種情況是當lua正在運行錯誤處理函數本身的時候,因為此時肯定不會再調用錯誤函數了,所以此時將會立即返回錯誤碼LUA_ERROR.在lua5.2中還定義了第三種情況,當finalizer(解譯器?) 拋出錯誤的時候,此時將會返回LUA_ERRGCMM(error in a GC metamethod)。這個代碼錶明錯誤不與調用函數本身有關。

 26.4 A Generic Call Function     這裡,將會建立一個wrapper(封裝器?)用來調用lua函數,使用了C中的vararg(可變參數?) 特性。假如稱我們的封裝器為call_va,參數為:1、要被調用的函數的名字;2、一個表示參數和返回值結果的字串;3、參數列表;4、儲存返回值結果的指標列表。使用API來處理所有的操作:
e.g.call_va(L,"f","dd>d",x,y,&z);
     字串"dd>d"表示“兩個類型為double的參數,一個類型為double的返回值”,這裡用"d"表示"double","i"表示"integer","s"表示"string"。用">"做分隔字元。而如果函數沒有返回值,那麼">"是可選的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.