手把手教你如何在Win中的Cocos-2dx-Lua調用Java
網上有很多文章,說怎么Lua調用C++最佳實踐,什么官網說明文檔,可以這么一說,這些所謂的教程全都是斷手斷腳的,對於小白來說,一到了關鍵位置,就無從下手。所以我現在記錄下我成功調用的經驗,希望幫到更多的人。
Cocos2d-x下Lua調用自定義C++類和函數的最佳實踐
HOW TO BIND A CUSTOM CLASS TO LUA RUNTIME
這個教程分為兩個部分,第一:toLua++的使用。第二:編譯代碼,調用代碼。
一、toLua++的使用。
這里所謂的toLua++ 的使用在cocos2dx到了3.x之后,得到了極大的優化,已經不需要用戶去手動書寫psk文件,至於什么是psk文件這里就不多說了,因為我們根本不會用到。3.x之后toLua++的使用已經集成再py腳本中了。所以這部分的使用其實只要細心就少了很多坑了。
1.工具下載與環境搭建
首先在你的cocos2dx工程的文件夾中找到/frameworks/cocos2d-x/tools/tolua/README.mdown
打開這個Readme文件。分別按順序的操作它的說明:
1.下載android-ndk-r9b
2.在電腦的環境變量中添加NDK_ROOT,指向剛剛下載的r9b
3.下載並安裝Python2.7.3(必須是2.7.3)
4.在電腦環境變量中添加Python2.7.3的安裝路徑
5.下載安裝pyyaml
6.下載pyCheetah並把它解壓到 ”/Python安裝路徑/Lib/site-packages/ “文件夾中
7.cmd去到cocos2d-x-3.4文件夾中的/tools/tolua/,運行命令:python genbindings.py
我用的時3.4版本的cocos2dx。經過一段時間的運行,如果看到以下畫面,證明你的配置已經成功了。接下來就是使用自定義的C++類了。
2.自定義C++類綁定Lua
2.1 wind7的cocos code IDE中新建Lua工程。
2.2 首先先構建一下工程,我構建了一下android模擬器。然后打開工程所在的目錄。去到一下文件夾里面。/frameworks/cocos2d-x/cocos/
cocos文件夾里裝載的都是這個工程的全部cocos的C++源碼。
2.3 在cocos文件夾中新建一個自己的文件夾。
2.4 在這個文件夾中加入自己定義的C++類和頭文件.這里我直接使用網上的類和頭文件,復制過來就好了。
.h://
// HNLuaTest.h
// cocos2d_libs
//
// Created by Eleven Chen on 14-8-5.
//
//
#ifndef __cocos2d_libs__HNLuaTest__
#define __cocos2d_libs__HNLuaTest__
#include "cocos2d.h"
#include
class Test : public cocos2d::Ref
{
public:
static std::string helloMsg();
static Test* create();
bool init();
static cocos2d::Vec2 left();
};
#endif /* defined(__cocos2d_libs__HNLuaTest__) */
CPP文件://
// HNLuaTest.cpp
// cocos2d_libs
//
// Created by Eleven Chen on 14-8-5.
//
//
#include "HNLuaTest.h"
using namespace cocos2d;
std::string Test::helloMsg()
{
return "Hello from HNLuaTest::helloMsg()";
}
Test* Test::create()
{
return new Test();
}
bool Test::init()
{
return true;
}
Vec2 Test::left()
{
return Vec2(0, 0);
}
2.5 通過腳本調用toLua++工具
2.5.1 . 去到工程目錄下的目標工程/frameworks/cocos2d-x/tools/tolua/
2.5.2 . 寫自己類的ini文件
這個步驟一定要非常小心,文件的格式一旦錯誤,就會導致后面的編譯失敗,按照我的經驗之談,最好就復制一個cocos2dx.ini ,然后把這個cocos2dx.ini命名為自己的類的ini,這里我命名為: HNLuaTest.ini
使用Notepad打開這個 HNLuaTest.ini 文件,修改它。
1.修改文件頭,修改為【HNLuaTest】
2.修改prefix
3.修改traget_namespace
4.修改headers 加上我們自己C++類的頭文件路徑
5.修改classes ,附上我們C++類中需要綁定的類名
以下的修改可以先暫時全部置空和不變。
2.5.4 . 寫自己的py腳本。
由於之前我們已經用命令行運行過了genbindings.py文件腳本,知道它就是綁定Lua的關鍵腳本,這里我們也同樣為了不必要的錯誤,先復制一個 genbindings.py,重命名為:genbindings_HNLuaTest.py。
接着修改這個genbindings_HNLuaTest.py文件。
在這腳本中的cmd_args一標簽中,先注釋了前面cocos2dx的ini文件,然后最后加上自己的ini文件命令。如下圖:
至於為何要注釋掉呢?你也可以不注釋,稍后你可以比較一下注釋前后的運行時間就明白了。另外一點是,前面的ini文件其實都已經被本來的genbindings.py執行過了,這里再執行一次就沒有意義了。
2.5.5 運行腳本
cmd到這個genbindings_HNLuaTest.py文件所在目錄python genbindings_HNLuaTest.py
如果報錯,不成功,一定是ini文件格式有問題,或者genbindings_HNLuaTest.py文件格式問題。
如果有需要可以在文章最后下載我的工程,然后找到這個兩個文件比對一下。
2.5.6 cpp與hpp文件
經過成功運行上面的腳本,因此會在auto文件夾中得到以下兩個文件。打開兩個文件,如果兩個文件中分別都有內容的話,證明生成成功了。
如果文件中的內容不為一個完整的hpp文件,和Cpp文件,即證明還是腳本運行出錯了。//cpp文件
目標工程/frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/lua_HNLuaTest_auto.cpp
//hpp文件
目標工程/frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/lua_HNLuaTest_auto.hpp
—–@到了最坑爹的地方了@—–
得到這兩個文件之后,你以為大功告成了嗎?你以為直接就可以在Lua中調用C++類了嗎?你以為你可以在Cocos的C++類中可以直接調用剛才的HNLuaTest類了嗎?你太天真了。
然而,網上很多教程都是針對mac系統的xCode的。什么把這兩個文件拷貝到工程中,然后再把源的Cpp和.h頭文件拷到工程目錄中,然后直接在AppDelegate.cpp的入口文件調用,然后再構建一下工程。靠·!!!那是xcode里面的,直接調用又是什么鬼?這個C++文件對應的.lua文件呢?沒有那個文件怎么引用那個C++類,難道Lua可以直接引用?
因為你翻看幾次那個frameworks文件夾,你就發現,其實cocos2dx的那些CPP文件都轉變為了.lua文件。
這些.lua文件都大部分放在了:..\frameworks\cocos2d-x\cocos\scripting\lua-bindings\script
那么我們自定義的那個c++類的.lua文件呢?
如果在Cocos-2dx-Lua工程中調用C++呢?
幸好,在我陷入一片無辜無助之后,我再次翻看了所有網上的文檔教程,功夫不負有心人,終於給我找到大神般的教程了。
Cocos2d-x 3.1 Lua Binding
這篇教程的最后提到編譯這個hpp與cpp文件,即腳本運行后得到的那個兩個文件。
根據那個教程(Android集成),我把它my的文件夾,改為自己的park,將他的coustom類改為我的HNLuaTest。
但我的步驟和他所說的還是有點不一樣,在修改好所有的mk文件之后,我先對這個工程進行了一次android的構建。
經過構建之后,你會發現在我們的luaApi文件夾中多了lua_HNLuaTest_auto_api.lua文件。
文件位於:...\frameworks\cocos2d-x\cocos\scripting\lua-bindings\auto\api
但你看到這個文件之后,你就放心多了,因為通過這個lua文件,你可以在lua工程直接就訪問Cpp中的類了。至於這個文件的生成為何在這里,你可以去研究一下genbindings.py腳本就知道了。
得到這個文件之后,就是說Lua調用C++類可以有文件依賴了,那么所有事情開始變得順利了。其實前面那些步驟簡直繁瑣到不要不要的,我在這里面整整沉溺了兩天時間。一個字:“繁亂”
不知道為何那么繁亂的語言竟然都有人用的,我簡直開始懷疑了發明這個人的智商。
好了,吐糟完了,由於收人錢財,替人消災,我還是要繼續下去呀。
得到這個文件之后,先可以在AppDelegate.cpp對這個文件訪問以下,畢竟HNLuaTest也是一個C++類。
教程中說需要這樣訪問:
其實在我們真實的3.4工程中,這個AppDelegate文件中,L早已經定義好了,所以我們直接這樣調用就好了:
這樣就可以了嗎?我以為真的可以了。然后我點擊“構建Apk”按鈕。彈出打包失敗。錯誤為:jni/../../Classes/AppDelegate.cpp:68: error: undefined reference to 'register_all_HNLuaTest(lua_State*)'
說這個方法沒有定義就被引用了。噢~!!是的,我們引入lua_HNLuaTest_auto.hpp這個頭文件。
打開..\frameworks\runtime-src\Classes文件夾
打開AppDelegate.cpp 和AppDelegate.h
你會發現,這兩個文件直接就引入了‘cocos2dx.h’,而在這個文件夾中壓根就沒有cocos2dx.h文件,然后我手多多打開了另一個文件
lua_module_register.h
字母上的意思就是模塊注冊的頭文件,而這個register看下去那么像C++注冊的意思?
打開之后你會驚人的發現:
這些引入與注冊不正是C++注冊到lua中的接口嗎?
然后再順藤摸瓜直上。先看看這個所謂的include文件在哪里?
沒錯,他們全部都在..\frameworks\cocos2d-x\cocos\scripting\lua-bindings\manual\
然后參照它們的引入方式,我也把lua_HNLuaTest_auto.hpp引入到AppDelegate.cpp文件中。included ../auto/lua_HNLuaTest_auto.hpp
好了,再重新構建一次andoid工程吧,應該會成功了吧。應該,應該,應該。~!靠···,沒錯,又失敗了。查找了一下錯誤說"lua_HNLuaTest_auto.cpp"文件中,無法找到“HNLuaTest.h”文件
為何會找不到這個頭文件,為何要引入這個頭文件呢?這個cpp不是已經引入了hpp頭文件了嘛?還要引入HNLuaTest.h嗎?帶着這些疑問我去lua_HNLuaTest_auto.cpp文件中的把included HNLuaTest.h這句話刪除了。再構建一次。
終於,終於,終於,構建成功了。實在淚流滿面了呀·好不容易呀·!然后就打包apk,也成功了,之后就安裝到手機中·······然后下班了·!!!周五晚,就不要加班了···趕緊出去嗨·!
周一繼續努力。我想既然都可以編譯成這樣了,理成功應該不遠了,雖然過程十分繁瑣,但基本原理心里有個框架了,等完全跑起來的時候 再回頭看看整個步驟邏輯。為何每一步都需要完成這些修改,這些修改針對的是什么?