tolua++原理理解
1.tolua++如何將c++物件匯入到lua裡
tolua++為每一個傳入lua的物件建立一個userdata,userdata的值,是c++物件的地址。userdata的metatable,是一個tolua++建立的,記錄了userdata對應c++型別資訊的表格,包括匯出的成員變數、成員函式等資訊。
對於成員變數的讀取賦值,tolua++是在metatable裡新建了.get和.set兩個表。兩個表裡分別儲存了以變數名為鍵,以讀取設定c函式為值的表項。在metatable的__index和__newindex裡,以變數名為鍵,從.get和.set表裡取得讀取設定函式並呼叫。對於成員函式的呼叫,只需要以函式名為鍵,函式為值,儲存在metatable裡就好了。
傳入c++物件的tolua++函式是tolua_pushusertype。一般情況下,第一次使用這個函式將一個c++物件push到lua堆疊上時,才會新建userdata。tolua++會以c++物件地址為鍵,userdata為值,將鍵值對儲存在tolua_ubox表裡。下次推入同樣的c++物件時,從這個表裡取出userdata推入堆疊即可。
2.tolua++如何處理型別的繼承
父類的metatable,是子類metatable的metatable。這樣呼叫父類方法時,就會去父類的metatable裡查找了。
tolua++還維護了一個tolua_super表,這個表以c++型別的metatable為鍵,以一個表格為值。這個值表格以型別名稱為鍵,以true為值,記錄了metatable對應c++型別的父類有哪些。這個表格可以用來幫助判斷物件是否是某一個型別(子類例項也可以認為是父類型別)
3.tolua++如何管理物件的生命週期
一般情況下,當lua裡對c++物件的引用變數可以被垃圾回收時,tolua++只是簡單的釋放userdata佔用的4位元組指標地址記憶體。但是也可以通過繫結或者程式碼指定的方式,讓tolua++真正釋放物件所佔記憶體。
繫結的方式,是指在將c++型別建構函式使用tolua++匯出到lua裡時,tolua++會自動生成new_local方法。如果在lua程式碼裡,用這個方法新建物件時,tolua++會呼叫tolua_register_gc方法,指明回收物件時回收物件記憶體。
在c++程式碼裡,使用tolua_pushusertype_and_takeownership;在lua程式碼裡,使用tolua.takeownership,都可以達到同樣的目的。
對於這些指定由tolua++回收記憶體的物件,如果其型別的解構函式也通過tolua++匯出了,則在回收記憶體時,會通過delete運算子,呼叫物件的解構函式。否則只會使用free方法回收。
tolua_register_gc方法,做的事情,是以物件指標為鍵,以物件metatable為值,將鍵值對儲存在tolua_gc表裡。在物件型別的metatable表的__gc方法裡,tolua++會檢查tolua_gc表是否包含以這個地址為鍵的表項。包含的話才會進行上述的記憶體回收工作。
4.其它
有的時候,在lua裡取得一個c++物件後,我們想賦給它一些只在lua環境下有意義的屬性。或者,我們想在lua裡擴充套件一個c++類。tolua++也提供了實現這種需求的機制。
tolua++在LUA_REGISTRY裡維護了一張tolua_peers表。這張表以表示c++物件的userdata為鍵,以一張表格t為值。t裡面就記錄了這個物件在lua裡擴充套件的屬性。
原文:https://blog.csdn.net/wtyqm/article/details/8977975