cocos2d-x 2.x 與 cocos2d-x 3.x 差異(tolua++)
cocos2d-x在2.x版本里就是用toLua++和.pkg文件這麼把自己註冊進Lua環境裏的,然而從cocos2d-x 3.x開始,用bindings-generator腳本代替了toLua++。
1、不用編寫.pkg和.h文件了,直接定義一個ini文件,註冊到Lua環境裏的模塊名是什麼,就行了。
2、摸清了toLua++工具的生成方法,改由Python腳本動態分析C++類,自動生成橋接的.h和.cpp代碼,不調用tolua++命令了
3、雖然不再調用tolua++命令了,但是底層仍然使用toLua++的庫函數,比如tolua_function,bindings-generator腳本生成的代碼就跟使用toLua++工具生成的幾乎一樣
接下來說怎麼用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
- #include "cocos2d.h"
- using namespace cocos2d;
- class MyClass : public Ref
- {
- public:
- MyClass() {};
- ~MyClass() {};
- bool init() { return true; };
- CREATE_FUNC(MyClass);
- int foo(int i);
- };
- #include "MyClass.h"
- int MyClass::foo(int i)
- {
- return i + 100;
- }
frameworks/cocos2d-x/tools/tolua/MyClass.ini
- [MyClass]
- prefix = MineClass # 添中前綴名XX,註冊文件頭及註冊函數名以前綴名(XX)組合命名
- target_namespace = my # 空間命名,調用時,以my.xxx, xxx爲自定義類的方法
- headers = %(cocosdir)s/../runtime-src/Classes/MyClass.h # 獲取自定義類的文件頭
- classes = MyClass # 需要註冊類YY(方法),同時註冊函數名以前綴名(XX)_YY組合命名
- cmd_args = {'cocos2dx.ini' : ('cocos2d-x', 'lua_cocos2dx_auto'), \
- 'MyClass.ini' : ('MyClass', 'lua_MyClass_auto'), \
- ...
至此,生成橋接文件的準備工作就做好了,執行genbindings.py腳本:
- python genbindings.py
注:若Python報錯,看下是否缺少yaml、Cheetah包,若是,安裝包就行了。
簡單解釋下編譯成後lua_MyClass_auto.cpp
- TOLUA_API int register_all_MineClass(lua_State* tolua_S)
- {
- //入口點,它創建管理的內部變量
- tolua_open(tolua_S);
- //創建新模塊
- tolua_module(tolua_S,"my",0);
- //註冊一個模塊或類
- tolua_beginmodule(tolua_S,"my");
- // 類的註冊
- lua_register_MineClass_MyClass(tolua_S);
- tolua_endmodule(tolua_S);
- return 1;
- }
- int lua_register_MineClass_MyClass(lua_State* tolua_S)
- {
- tolua_usertype(tolua_S,"MyClass"); //註冊用戶類型
- tolua_cclass(tolua_S,"MyClass","MyClass","cc.Ref",nullptr); //註冊類
- tolua_beginmodule(tolua_S,"MyClass"); //註冊模塊
- tolua_function(tolua_S,"new",lua_MineClass_MyClass_constructor); //綁定函數(將Lua裏面MyClass對象的”new”綁定到你的lua_MineClass_MyClass_constructor()函數中去.)
- tolua_function(tolua_S,"init",lua_MineClass_MyClass_init);
- tolua_function(tolua_S,"foo",lua_MineClass_MyClass_foo);
- tolua_function(tolua_S,"create", lua_MineClass_MyClass_create);
- tolua_endmodule(tolua_S);
- std::string typeName = typeid(MyClass).name(); //保存註冊類
- g_luaType[typeName] = "MyClass";
- g_typeCast["MyClass"] = "MyClass";
- return 1;
- }
- cobj = (MyClass*)tolua_tousertype(tolua_S,1,0); //是將數據棧下的對象以(CTest* )的指針形式彈出來。
2.編譯運行
打開Classes/lua_module_register.h文件,添加頭文件
- #include "tolua++/lua_MyClass_auto.hpp"
- register_all_MineClass(L);
lua代碼:
- function myadd(x, y)
- -- 自定義
- local test = my.MyClass:create()
- print("lua bind: " .. test:foo(99))
- return x + y
- end