C++集成lua

tolua++

C++最常用的類對(duì)象,它的導(dǎo)入要比函數(shù)導(dǎo)入復(fù)雜許多。
本質(zhì)上C++的對(duì)象是一個(gè)指針, 一般是用UserData包裝,綁定元表信息。
元表用C++類結(jié)構(gòu)建立起來(lái),告訴lua如何讀寫C++對(duì)象。

有個(gè)自動(dòng)導(dǎo)出C++的工具,tolua++。
步驟:

  1. 寫個(gè)描述文件,和C++頭文件很像
  2. 運(yùn)行tolua++命令生成cpp代碼,里面有tolua_module_open的注冊(cè)函數(shù)
  3. 在Lua引擎初始化后,調(diào)用tolua_module_open注入。
$#include"hello.h"

namespace hello{
void show();

class MyClass
{
public:
MyClass();
~MyClass();
void DoSomething();
};
}
/* Open function */
TOLUA_API int tolua_hello_open (lua_State* tolua_S)
{
tolua_open(tolua_S);
tolua_reg_types(tolua_S);
tolua_module(tolua_S,NULL,0);
tolua_beginmodule(tolua_S,NULL);
tolua_module(tolua_S,"hello",0);
tolua_beginmodule(tolua_S,"hello");
tolua_function(tolua_S,"show",tolua_hello_hello_show00);
#ifdef __cplusplus
tolua_cclass(tolua_S,"MyClass","hello::MyClass","",tolua_collect_hello__MyClass);
#else
tolua_cclass(tolua_S,"MyClass","hello::MyClass","",NULL);
#endif
tolua_beginmodule(tolua_S,"MyClass");
tolua_function(tolua_S,"new",tolua_hello_hello_MyClass_new00);
tolua_function(tolua_S,"new_local",tolua_hello_hello_MyClass_new00_local);
tolua_function(tolua_S,".call",tolua_hello_hello_MyClass_new00_local);
tolua_function(tolua_S,"delete",tolua_hello_hello_MyClass_delete00);
tolua_function(tolua_S,"DoSomething",tolua_hello_hello_MyClass_DoSomething00);
tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
return 1;
}

C++集成Lua的麻煩

C++集成lua有不少坑點(diǎn)。

  1. 內(nèi)存管理【這是最麻煩的地方
    lua有自動(dòng)垃圾回收,C++要手動(dòng)管理。
  2. 常用類型的導(dǎo)出
    c++的基本類型和模版類型非常多,lua通常只支持double和Lua.Table 常用的int64,vector,map的處理就那么順心了。
  3. 繼承體系
    這個(gè)反而簡(jiǎn)單了,C++的多繼承體系很容易可以用lua的元表模擬起來(lái)。
  4. 遞歸調(diào)用、異常、協(xié)程
    難免出現(xiàn)這種情況,C++ -> Lua -> C++ -> Lua。中間發(fā)生異常如何處理?協(xié)程中斷如何處理?一不小心就程序狀態(tài)不對(duì),內(nèi)存泄漏啥的。

Lua管理C++對(duì)象

實(shí)際也就是Lua管理C++的指針和內(nèi)存。
兩個(gè)簡(jiǎn)單情況:

  1. Lua完全負(fù)責(zé)C++對(duì)象的生命周期
    這時(shí)需要把C++對(duì)象包裝成UserData,在元表里加入__gc的方法,lua垃圾回收時(shí)就可以自動(dòng)回收函數(shù)了。
    也可以在元表里導(dǎo)入new和delete方法,lua代碼里調(diào)用。
    在tolua++里,如果導(dǎo)入了構(gòu)造函數(shù)和析構(gòu)函數(shù),就有三個(gè)元表鍵值new,delete,new_local。
  2. Lua運(yùn)行期間C++對(duì)象一直有效
    如C++靜態(tài)變量,導(dǎo)出到lua里時(shí)不需要負(fù)責(zé)內(nèi)存回收的,這時(shí)最好使用lightuserdata,就保存?zhèn)€指針到lua里。

C++管理Lua對(duì)象

這是有一種復(fù)雜情況,C++和Lua里都可以創(chuàng)建和釋放對(duì)象。
這時(shí)的核心是一方操作要通知另一方。創(chuàng)建和釋放都不能簡(jiǎn)單的處理了。
一般是維護(hù)一個(gè)表,記錄對(duì)象,釋放時(shí)修改下表,來(lái)通知對(duì)方。LuaL_ref就是為此設(shè)計(jì)的。

具體實(shí)現(xiàn)上有一個(gè)大的分歧:

  1. C++和Lua都可以刪除對(duì)象,一方刪除需要通知另一方。
    1. C++刪除通知Lua,這個(gè)相對(duì)好處理些,lua里可以做到一個(gè)C++對(duì)象只有一個(gè)UserData。C++可以獲取到這個(gè)UserData,然后清空指針。
    2. Lua刪除通知C++,這個(gè)就不好辦,Lua是不可能知道C++哪兒保存了對(duì)象的指針的。最常見的方法是使用引用計(jì)數(shù)了。
  2. C++和Lua不都可以刪除對(duì)象
    1. 只有一方可以刪除。一般是C++刪除,Lua可以判斷是否被刪了。
    2. 引用計(jì)數(shù)。小缺點(diǎn)是引用計(jì)數(shù)維護(hù)不好就慘了。

關(guān)于對(duì)象內(nèi)存管理的小結(jié)

實(shí)際使用中三種情況比較常見

  1. Lua完全管理C++對(duì)象,Lua里創(chuàng)建刪除,C++層不保存指針。
  2. C++完全管理對(duì)象,刪除時(shí)會(huì)通知Lua,Lua里可以判斷對(duì)象是否還有效。Lua只使用,創(chuàng)建對(duì)象也是通過(guò)C++層特殊處理。
  3. C++獲取保存Lua的表和閉包回調(diào)。對(duì)象的生命周期是lua負(fù)責(zé),但是C++會(huì)設(shè)置下,讓Lua不能把用著的對(duì)象給回收了。
    1. 同樣也可以C++層維護(hù)引用計(jì)數(shù),lua里操作引用計(jì)數(shù),創(chuàng)建UserData時(shí)加一,回收時(shí)減一。

tolua++的實(shí)現(xiàn)里,是Lua可以選擇是否管理C++對(duì)象的生命周期,有兩個(gè)典型的方法takeownershipreleaseownership。比較弱啊。
Cocos2dx-lua對(duì)tolua++有不少改動(dòng)。
主要參考:

http://blog.csdn.net/wtyqm/article/details/8977975
http://blog.csdn.net/wtyqm/article/details/9106137

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,793評(píng)論 11 349
  • 第一篇 語(yǔ)言 第0章 序言 Lua僅讓你用少量的代碼解決關(guān)鍵問(wèn)題。 Lua所提供的機(jī)制是C不擅長(zhǎng)的:高級(jí)語(yǔ)言,動(dòng)態(tài)...
    testfor閱讀 2,947評(píng)論 1 7
  • 1. 寫在前面 很多時(shí)候我們都需要借助一些腳本語(yǔ)言來(lái)為我們實(shí)現(xiàn)一些動(dòng)態(tài)的配置,那么就會(huì)涉及到如何讓腳本語(yǔ)言跟原生語(yǔ)...
    杰嗒嗒的阿杰閱讀 3,502評(píng)論 9 31
  • 最近一朋友正準(zhǔn)備跳槽,就從各處搜索整理一些基礎(chǔ),便于朋友復(fù)習(xí),也便于自己復(fù)習(xí)查看. 1. 回答person的ret...
    smile麗語(yǔ)閱讀 1,901評(píng)論 0 7
  • 我并不是特別喜歡孤獨(dú),但是孤獨(dú)是最讓我放松的狀態(tài)。 與人交際容易讓我緊張,無(wú)法放松。所以一直以來(lái)我都盡可能的避免與...
    小王的小桌子閱讀 189評(píng)論 0 0

友情鏈接更多精彩內(nèi)容