首先lua並不支援你將Class傳到script這邊,lua只支援將一個C風格的全域函式指標傳過去,因此一切行動都是從全域函式開始的。
基本概念就是將C++的一組全域函式傳到lua這邊,然後用lua的table將它們包裝的像個物件一樣,table會內含一個物件指標,這就是大致上的實作方向了。
首先在C++這裡寫個全域函式負責動態配置物件,將它的函式指標傳到lua之後會扮演建構子的角色,產生的物件指標會用lua的userdata來儲存。
另外再寫幾個全域函式來負責操作物件指標,它們的函式指標傳到lua之後會扮演成員函式的角色。
將上面這些函式裝到lua的table上面就可以直覺的使用C++的物件了。
解構子則不需要以上做法,在儲存物件指標的userdata上面就可以指定解構行為了。這裡需要注意一點,lua的解構時間點跟C++不同,因為lua的垃圾收集機制不是當變數無人使用時就會去清理,所以不要以為區域物件在離開該區域時就會當場解構,而且由於指標的size太小,lua根本不知道指標背後咬了多大一塊記憶體,可能會累積超多物件才解構,你最好自己親自呼叫"__gc"來解構,或者
用collectgarbage("collect")
強制要求立刻
清理。要傳給lua使用的全域函式有固定的格式(lua_CFunction),而且從lua取得參數以及送回傳值給lua都需要呼叫lua介面來執行,你可以看到網路上有很多教學是自己寫個Wrapper類別來當中間層,然後為類別量身打造一系列全域函式,這樣寫起來會很累,而且不能封裝的全域函式會破壞OO架構,程式碼不會好看到哪去。
幸虧C++還有樣版這樣的特別武器,可將上述手續給包裝起來,真的輕鬆超多的,我的luapp專案就是在做這件事,luapp已經將這份工作包裝的很舒服了。
當然檯面上還有其他更成熟的專案提供更全面的功能,不過以我的需求來說,自製的luapp已經堪用了。
沒有留言:
張貼留言