tolua++實現分析

項目正在使用cocos2dx的lua綁定,綁定的方式是tolua++。對大規模使用lua代碼信心不是很足,花了一些時間閱讀tolua++的代碼,但願對綁定實現的瞭解,有助於項目對lua代碼的把控。從閱讀結果上來看,起碼在內存管理上,幫助仍是很大的。c++

 

1.tolua++如何將c++對象導入到lua裏函數

tolua++爲每個傳入lua的對象創建一個userdata,userdata的值,是c++對象的地址。userdata的metatable,是一個tolua++創建的,記錄了userdata對應c++類型信息的表格,包括導出的成員變量、成員函數等信息。lua

對於成員變量的讀取賦值,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++如何處理類型的繼承ip

父類的metatable,是子類metatable的metatable。這樣調用父類方法時,就會去父類的metatable裏查找了。內存

tolua++還維護了一個tolua_super表,這個表以c++類型的metatable爲鍵,以一個表格爲值。這個值表格以類型名稱爲鍵,以true爲值,記錄了metatable對應c++類型的父類有哪些。這個表格能夠用來幫助判斷對象是不是某一個類型(子類實例也能夠認爲是父類類型)get

 

—————————————————

 

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裏擴展的屬性。

 

cocos2dx並無徹底使用tolua++的方式,而是本身進行了一些修正。下篇博客應該會記錄修正的緣由和方式,並介紹一些cocos2dx lua bind特定的東西。

相關文章
相關標籤/搜索