手把手教你如何在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.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 <string>
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,也成功了,之后就安装到手机中·······然后下班了·!!!周五晚,就不要加班了···赶紧出去嗨·! 周一继续努力。我想既然都可以编译成这样了,理成功应该不远了,虽然过程十分繁琐,但基本原理心里有个框架了,等完全跑起来的时候 再回头看看整个步骤逻辑。为何每一步都需要完成这些修改,这些修改针对的是什么?