1. 程式人生 > 實用技巧 >lua呼叫自定義c++類

lua呼叫自定義c++類

>>> hot3.png

【嘮叨】

本節要講的是如果將自己寫的C++類註冊進Lua環境,讓Lua去呼叫自定義的C++類

網上有很多都是用原始的tolua++工具來註冊C++類的,我看了很多這樣的教程,感覺操作起來十分麻煩,而且也很難看懂他們到底在講什麼。

其實,在cocos2dx v3.2版本中,提供了bindings-generator指令碼來封裝toLua++的用法,從而節省了工作量。


【致謝】

http://segmentfault.com/blog/hongliang/1190000000718145(講得非常好!)

http://cn.cocos2d-x.org/article/index?type=code-ide&url=/doc/cocos-docs-master/manual/code-ide/binding-custom-class-to-lua/zh.md

(官方文件)


【使用工具】

Windows7 x64

Cocos2dx v3.2

Cocos Code IDE 1.0.1 (支援自定義類的智慧提示功能)


python 2.7.x(v3.2版本不一定要2.7.3,我用2.7.8也成功了的)

NDK r9d,解壓並配置環境變數NDK_ROOT(v3.2版本不一定要r9b,我用r9d成功了的)

pyyaml ,安裝到 "Python的安裝目錄\Lib\site-packages"

http://pyyaml.org/download/pyyaml/PyYAML-3.10.win32-py2.7.exe

Cheetah ,並解壓到 "Python的安裝目錄\Lib\site-packages"

https://raw.github.com/dumganhar/my_old_cocos2d-x_backup/download/downloads/Cheetah.zip

dos2unix ,windows下可能在執行指令碼時有這個錯誤。

解壓到一某個目錄下面, 並設定PATH環境變數的值指向bin目錄下。

http://waterlan.home.xs4all.nl/dos2unix/dos2unix-7.1-win32.zip




【繫結方法】

以下介紹的是在Windows7 + VS2013 + Cocos Code IDE

並使用Cocos Code IDE建立的Lua專案,繫結方法。


1、將自定義的C++程式碼放在frameworks\runtime-src\Classes 下

當然放哪裡是隨意的,我喜歡放在Classes下。

wKioL1RL0zrCwXR9AAF0rHubdVQ695.jpg


2、新增自定義類的.ini檔案

frameworks\cocos2d-x\tools\tolua 中,複製一份該資料夾下cocos2dx.ini的配置資訊,然後修改一些引數,改成我們自定義類的引數。

wKioL1RL1NvAEgUdAAAxRDlqd4k342.jpg

以下列出需要修改的引數配置:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [custom_api] #prefix會被新增到生成的函式.你也可以選擇不新增這個到你的模板 prefix=custom_api #所有的類都會嵌入到這個名稱空間 target_namespace=my #類所在的路徑,如果有多個,用空格隔開 headers=%(cocosdir)s/../runtime-src/Classes/PanZoomLayer.h #需要註冊的類,如果有多個,用空格隔開 classes=PanZoomLayer #不提供給Lua的public成員函式 skip=PanZoomLayer::[onTouchesBeganonTouchesMovedonTouchesEndedinitonEnteronExitupdate] #這些全空就好了 rename_functions= rename_classes= remove_prefix= classes_have_no_parents= base_classes_to_skip= abstract_classes= script_control_cpp=no


3、genbindings.py 新增自定義的配置.ini

frameworks\cocos2d-x\tools\toluagenbindings.py中的129行找到cmd_args

將我們自定義的custom_api.ini 新增進去,並註釋掉其他.ini(這些已經不需要重新生成)

wKioL1RL2RGx9zP1AAMRjTrGUh4452.jpg


4、執行genbindings.py 指令碼

在終端執行genbindings.py 指令碼。

在這裡,我是直接寫了一個批處理檔案 .bat 。

注意:只要需要用到的工具都下載,安裝,配置好了,一般就能生成成功。

生成失敗的,基本都是因為工具沒有配置好。

wKiom1RL2WPAnAYnAAD5jo7zWb8151.jpg


生成成功後,在frameworks\cocos2d-x\cocos\scripting\lua-bindings\auto 中會找到我們生成的C++的橋接檔案, lua_custom_api_auto.cpplua_custom_api_auto.hpp

wKioL1RL2y6DVRX7AAB3H2ztpRw355.jpg


其中 lua_custom_api_auto.hpp 中的register_all_custom_api 就是我們用來將PanZoomLayer類註冊到Lua環境中的關鍵函式。

wKiom1RL3CvQsTBNAAFpA5UFDjQ936.jpg


以及在frameworks\cocos2d-x\cocos\scripting\lua-bindings\auto\api 中也能夠找到我們提供給Lua呼叫的介面檔案。

wKiom1RL23LiE_2EAADt_Dl4paM431.jpg


5、編譯註冊到Lua

註冊自定義類的函式在我們的lua_custom_api_auto.hpp 中可以看到。

register_all_custom_api(lua_State* tolua_S)

wKiom1RL3CvQsTBNAAFpA5UFDjQ936.jpg


使用 VS2013 開啟frameworks\runtime-src\proj.win32 下的工程。

(1)將自定義的類 PanZoomLayer 新增到專案工程的Classes下。

wKiom1RL3c6yZ4PEAAB3OlLbZhk958.jpg

(2)將lua_custom_api_auto.cpp、lua_custom_api_auto.hpp新增到工程liblua的auto下。

wKiom1RL3qDikRCvAAG_ncnZkvQ661.jpg

(3)新增lualib工程的檔案搜尋路徑。

$(EngineRoot)../runtime-src/Classes 路徑加進去。

wKioL1RL32rhaAU8AAE8tMBgTpw591.jpg

(4)編輯frameworks\runtime-src\Classes 下的入口類 AppDelegate.cpp

>新增:lua_custom_api_auto.hpp標頭檔案

wKiom1RL3Lug2Np1AAAqi0a-IYQ249.jpg

> 註冊:register_all_custom_api(state)

> 注意:register_all_custom_api 的上下兩句話,必須加上!

wKioL1RL3Q2QDNclAAHPrYX_6BI408.jpg

(5)編譯執行整個專案,完成C++類的註冊到Lua。

然後就可以再Lua中愉快的使用自定義的類了!




【開啟智慧提示】

雖然我們將我們自定義的C++類註冊到了Lua中呼叫,但是在Cocos Code IDE中卻沒有我們自定義類的智慧提示。

我們需要修改一些配置,讓Cocos Code IDE加上對我們自定義類的智慧提示


1、Cocos2dx引擎中的智慧提示

首先我們來看一下Cocos Code IDE中cocos2dx引擎的智慧提示是怎麼搞的。

隨便找個 cc.Label 把!

我們按住鍵盤的 ctrl 鍵,然後點選 cc Label,就會跳轉到宣告它們的地方。

wKiom1RL4vGjjv10AAAi5Dt7P4A782.jpg

檔案跳轉到了如下兩幅圖的地方:

wKioL1RL4-KhMI4XAAFP955pFxc307.jpg


wKioL1RL4-OihcZkAAGNcLJuOOY308.jpg


可能看到以上兩幅圖,你就明白應該怎麼給我們自定義的C++類加上智慧提示了吧?


我們先找到以下檔案路徑:(可能每個人的不一樣)

\CocosCodeIDE\configuration\org.eclipse.osgi\bundles\61\1\.cp\resource\cocos2dx-3.2

可以發現該路徑下有一個 api.zip 這個壓縮包。

我們將其 api.zip 解壓出來看看裡面都是什麼東西。wKiom1RL5I7QTUXfAAE4J2kdwJU349.jpg

wKioL1RL5prSbATiAAF56z9JNAI653.jpg


wKiom1RL9vuT2T9LAAJ2fGK5-kU348.jpg


可以發現裡面全是cocos2dx的C++類提供給Lua的介面宣告。

這些也就是IDE中智慧提示的原因。


2、新增自定義類的智慧提示(方式一)

我們仿照 api.zip 中的 cc.lua 和 label.lua 來寫一個自定義類的介面宣告。

> my.lua :宣告名稱空間

> PanZoomLayer.lua:宣告自定義類。(這個在使用指令碼繫結時,自動生成)

其中PanZoomLayer.lua 在使用genbindings.py指令碼時,就自動生成了的。

就在frameworks\cocos2d-x\cocos\scripting\lua-bindings\auto\api 中。

那麼,我們再寫一個 my.lua ,也放在這個目錄下好了。

其中,my.lua 程式碼如下:

1 2 3 4 5 6 7 8 9 -------------------------------- --@modulemy -------------------------------------------------------- --themyPanZoomLayer --@field[parent=#my]PanZoomLayer#PanZoomLayerPanZoomLayerpreloadedmodule returnnil


wKioL1RL947iMVEQAAEoZxR9ge8316.jpg


PanZoomLayer.lua 程式碼如下:

wKioL1RL6cCiCX9WAAM6bAzCK7Y304.jpg


然後我們將 my.lua 和PanZoomLayer.lua 一併壓縮到 myapi.zip 中

就放在\frameworks\cocos2d-x\cocos\scripting\lua-bindings\auto\api 中好了。

wKioL1RL6wPiJgirAAEhY5DYprw732.jpg


然後我們開啟Cocos Code IDE的工程專案,配置屬性。

Lua->Build Path->Libraries->Add External Zips

將我們的 myapi.zip 壓縮包新增進去,點選“確定”。

wKiom1RL6y6whGwdAAL9na5GZdw128.jpg


這樣,就可以在 Cocos Code IDE 中愉快的玩我們自定義的類了。

有智慧提示,就是爽啊!!!i_f07.gif

wKioL1RL7FrhojIFAABaW9-L54M677.jpg

wKiom1RL7AiDort9AACENIlt5Ec002.jpg

wKioL1RL7KLjVoFUAAHqxAbDB40728.jpg


3、新增智慧提示(方式二)

通過上面的方式一的方法雖然可以有智慧提示,可是後來我發現定義的名稱空間 my 卻無法識別。這樣的結果將導致建立的 my.PanZoomLayer:create() 賦值給 self 的成員 self.pzLayer 後,繼續使用self.pzLayer 時,對應的函式又無法提示了。

wKiom1RMtE6xkHlyAABfA0aiUEs010.jpg

所以這裡我們通過修改官方智慧提示包 api.zip ,來達到更加的智慧提示的效果。

操作方法和方式一類似,我們先將官方的提示包 api.zip 解壓出來,最好將其備份一份。

檔案在:

\Cocos Code IDE\configuration\org.eclipse.osgi\bundles\61\1\.cp\resource\cocos2dx-3.2

wKioL1RMtUmSCXySAAEYK8cc_HA675.jpg


然後我們將我們自定義提示包 my.luaPanZoomLayer.lua 放入 api 資料夾中。

wKiom1RMtkTQSQsKAAJeXFL4uHQ687.jpg


然後在 api 資料夾中找到 global.lua 這個全域性宣告檔案。

將我們自定義的名稱空間 my 宣告進去。

1 2 --themymodule --@field[parent=#global]my#mymypreloadedmodule


wKioL1RMteOzU_PZAAObQErZ1ys759.jpg


儲存關閉,將 api 資料夾壓縮成 api.zip 包。

wKioL1RMtu7xnSPPAADALEjJJDI186.jpg

然後重新整理我們的專案工程,然後再來試試我們自定義類的智慧提示效果。

可以發現,自定義的類的智慧提示已經和 官方的智慧提示功能 完全一致了。

又可以愉快的玩耍啦!!!i_f28.gif

wKiom1RMtuugmiVrAAJ-31JEBW4104.jpg




【遇到的問題】


1、指令碼生成出錯

wKiom1RLzk7A7N1lAANtk3-0x9o550.jpg

wKioL1RLzqDy_XmDAALksUIjK3g521.jpg

這些出錯都是由於沒有配置pyyaml、Cheetah、dos2unix 引起的,都下過來配置一下即可。


2、編譯到Android手機出錯

上面的配置完成後IOS的部分是可以正常執行的,但是這個時候編譯android時不通過的。

因為 AppDelegate.cpp 裡面呼叫的 register_all_MyClass(L) 方法在android不存在,android的專案裡並沒有配置去編譯對應的 PanZoomLayer.cpp 檔案和後續生成的 lua_custom_api_auto.cpp。

所以需要在android端配置Android.mk檔案,讓專案編譯時去編譯這兩個C++檔案才行。


(1)首先配置JNI下面的Android.mk檔案,讓JNI部分編譯時去編譯PanZoomLayer.cpp:

編輯 frameworks/runtime-src/proj.android/jni/Android.mk

LOCAL_SRC_FILES 引數的後面新增:(注意後面的 \ ,僅最後一行不加斜槓)

../../Classes/PanZoomLayer.cpp

wKiom1RL-RKiDEywAAH-iwiWIIY738.jpg


LOCAL_C_INCLUDES 引數的後面新增:(注意後面的\,僅最後一行不加斜槓

$(LOCAL_PATH)/../../Classes

wKioL1RL-XvyZNt9AABZE6y2eYQ966.jpg


(2)然後配置frameworks/cocos2d-x/cocos/scripting/lua-bindings/Android.mk檔案。

LOCAL_SRC_FILES 引數的後面新增:(注意後面的\,僅最後一行不加斜槓

auto/lua_custom_api_auto.cpp

wKiom1RL-TyA_qxTAAHW36-i5xM024.jpg


LOCAL_C_INCLUDES 引數的後面新增:(注意後面的\,僅最後一行不加斜槓

$(LOCAL_PATH)/../../../../runtime-src/Classes

wKioL1RL-ZyS6JLUAAGIxbrx4oo396.jpg


(3)然後 Build-Runtime,將專案在Android端編譯一下。

wKiom1RL-YTCkK43AAE9zSpAmfo656.jpg


(4)若編譯成功,就可以在Android手機上測試了!





轉載於:https://my.oschina.net/guyson/blog/338376