我所理解cocos2d-x 3.6 lua -- Cocos如何綁定Lua自定義類

cocos2d-x 2.x 與 cocos2d-x 3.x 差異(tolua++)


    cocos2d-x在2.x版本里就是用toLua++和.pkg文件這麼把自己註冊進Lua環境裏的,然而從cocos2d-x 3.x開始,用bindings-generator腳本代替了toLua++。


    bindings-generator腳本的工作機制是:
        1、不用編寫.pkg和.h文件了,直接定義一個ini文件,註冊到Lua環境裏的模塊名是什麼,就行了。
        2、摸清了toLua++工具的生成方法,改由Python腳本動態分析C++類,自動生成橋接的.h和.cpp代碼,不調用tolua++命令了

        3、雖然不再調用tolua++命令了,但是底層仍然使用toLua++的庫函數,比如tolua_function,bindings-generator腳本生成的代碼就跟使用toLua++工具生成的幾乎一樣


    bindings-generator腳本掌握了生成toLua++橋接代碼的主動權,不僅可以省下大量的.pkg和.h文件,而且可以更好地插入自定義代碼,達到cocos2d-x環境下的一些特殊目的,比如內存回收之類的,所以cocos2d-x從3.x開始放棄了toLua++和.pkg而改用了自己寫的bindings-generator腳本是非常值得讚賞的聰明做法。

    接下來說怎麼用bindings-generator腳本:
        1、寫自己的C++類,按照cocos2d-x的規矩,繼承cocos2d::Ref類,以便使用cocos2d-x的內存回收機制。
        2、編寫一個.ini文件,讓bindings-generator可以根據這個配置文件知道C++類該怎麼暴露出來
        3、修改bindings-generator腳本,讓它去讀取這個.ini文件
        4、執行bindings-generator腳本,生成橋接C++類方法
        5、用VS2012將自定義的C++類和生成的橋接文件加入工程,不然編譯不到
        6、修改AppDelegate.cpp,執行橋接方法,自定義的C++類就註冊進Lua環境裏了。

    首先是自定義的C++類。我習慣將文件保存在frameworks/runtime-src/Classes/目錄下:

    frameworks/runtime-src/Classes/MyClass.h

[cpp] view plain copy
  1. #include "cocos2d.h"  
  2.   
  3. using namespace cocos2d;  
  4.   
  5. class MyClass : public Ref  
  6. {  
  7. public:  
  8.   MyClass()   {};  
  9.   ~MyClass()  {};  
  10.   bool init() { return true; };  
  11.   CREATE_FUNC(MyClass);  
  12.   
  13.   int foo(int i);  
  14. };  
    frameworks/runtime-src/Classes/MyClass.cpp

[cpp] view plain copy
  1. #include "MyClass.h"  
  2.   
  3. int MyClass::foo(int i)  
  4. {  
  5.   return i + 100;  
  6. }  
    然後編寫.ini文件。在frameworks/cocos2d-x/tools/tolua/目錄下能看到genbindings.py腳本和一大堆.ini文件,這些就是bindings-generator的實際執行環境了。隨便找一個內容比較少的.ini文件,複製一份,重新命名爲MyClass.ini。大部分內容都可以湊合不需要改,這裏僅列出必須要改的重要部分:
    frameworks/cocos2d-x/tools/tolua/MyClass.ini

[cpp] view plain copy
  1. [MyClass]  
  2. prefix           = MineClass                                            # 添中前綴名XX,註冊文件頭及註冊函數名以前綴名(XX)組合命名  
  3. target_namespace = my                                               # 空間命名,調用時,以my.xxx, xxx爲自定義類的方法  
  4. headers          = %(cocosdir)s/../runtime-src/Classes/MyClass.h    # 獲取自定義類的文件頭  
  5. classes          = MyClass                                          # 需要註冊類YY(方法),同時註冊函數名以前綴名(XX)_YY組合命名  
    frameworks/cocos2d-x/tools/tolua/genbindings.py
[cpp] view plain copy
  1. cmd_args = {'cocos2dx.ini' : ('cocos2d-x''lua_cocos2dx_auto'), \  
  2.             'MyClass.ini' : ('MyClass''lua_MyClass_auto'), \  
  3.             ...  
    (其實這一步本來是可以省略的,只要讓genbindings.py腳本自動搜尋當前目錄下的所有ini文件就行了,不知道將來cocos2d-x團隊會不會這樣優化)
至此,生成橋接文件的準備工作就做好了,執行genbindings.py腳本:

[cpp] view plain copy
  1. python genbindings.py  
    成功執行genbindings.py腳本後,會在frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/目錄下看到新生成的文件:


        


    注:若Python報錯,看下是否缺少yaml、Cheetah包,若是,安裝包就行了。

    簡單解釋下編譯成後lua_MyClass_auto.cpp

[cpp] view plain copy
  1. TOLUA_API int register_all_MineClass(lua_State* tolua_S)  
  2. {  
  3.     //入口點,它創建管理的內部變量  
  4.     tolua_open(tolua_S);  
  5.     //創建新模塊  
  6.     tolua_module(tolua_S,"my",0);  
  7.     //註冊一個模塊或類  
  8.     tolua_beginmodule(tolua_S,"my");  
  9.     // 類的註冊  
  10.     lua_register_MineClass_MyClass(tolua_S);  
  11.   
  12.     tolua_endmodule(tolua_S);  
  13.     return 1;  
  14. }  
    註冊類:

[cpp] view plain copy
  1. int lua_register_MineClass_MyClass(lua_State* tolua_S)  
  2. {  
  3.     tolua_usertype(tolua_S,"MyClass");                                   //註冊用戶類型  
  4.     tolua_cclass(tolua_S,"MyClass","MyClass","cc.Ref",nullptr);          //註冊類  
  5.   
  6.     tolua_beginmodule(tolua_S,"MyClass");                                //註冊模塊  
  7.         tolua_function(tolua_S,"new",lua_MineClass_MyClass_constructor); //綁定函數(將Lua裏面MyClass對象的”new”綁定到你的lua_MineClass_MyClass_constructor()函數中去.)  
  8.         tolua_function(tolua_S,"init",lua_MineClass_MyClass_init);  
  9.         tolua_function(tolua_S,"foo",lua_MineClass_MyClass_foo);  
  10.         tolua_function(tolua_S,"create", lua_MineClass_MyClass_create);  
  11.     tolua_endmodule(tolua_S);  
  12.     std::string typeName = typeid(MyClass).name();                      //保存註冊類  
  13.     g_luaType[typeName] = "MyClass";  
  14.     g_typeCast["MyClass"] = "MyClass";  
  15.     return 1;  
  16. }  
    綁定函數,要注意下:

[cpp] view plain copy
  1. cobj = (MyClass*)tolua_tousertype(tolua_S,1,0); //是將數據棧下的對象以(CTest* )的指針形式彈出來。  
    從棧中彈出對象(其實是自定類的對象),接着把對象引用方法(包括含參數及handle)返回結果壓棧,實現c、lua之間互相調用了。


2.編譯運行 

    打開Classes/lua_module_register.h文件,添加頭文件 

[cpp] view plain copy
  1. #include "tolua++/lua_MyClass_auto.hpp"  
    在static int lua_module_register(lua_State* L)添加註冊函數

[cpp] view plain copy
  1. register_all_MineClass(L);  
    若vs2012編譯錯誤,估計都是沒把源文件及生成的文件加入工程; 若有特殊處理,比如更換genbindings.py腳本生成文件路徑,注意在vs2012環境->屬性->c/c++->附加包含目錄,添加路徑。

lua代碼:

[cpp] view plain copy
  1. function myadd(x, y)  
  2.     -- 自定義  
  3.     local test = my.MyClass:create()  
  4.     print("lua bind: " .. test:foo(99))  
  5.     return x + y  
  6. end  
編譯運行:





-----------------------------------------------------------------------------------------------------------------------------
本文轉自:http://blog.csdn.net/rexuefengye/article/details/46553239
發佈了23 篇原創文章 · 獲贊 8 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章