Lua ——Cocos之_Lua调用C++类

知识养成了思想,思想同时又在融化知识。这篇文章主要讲述Lua ——Cocos之_Lua调用C++类相关的知识,希望能为你提供帮助。
【唠叨】

        本节要讲的是如果将自己写的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


    【MAC】参见:http://blog.csdn.net/guo_hongjun1611/article/details/39852873




【绑定方法】
    以下介绍的是在  Windows7 + VS2013 + Cocos Code IDE。
        并使用Cocos Code IDE创建的Lua项目,绑定方法。


1、将自定义的C++代码放在  frameworks\\runtime-src\\Classes 下
        当然放哪里是随意的,我喜欢放在Classes下。

Lua ——Cocos之_Lua调用C++类

文章图片



2、添加自定义类的.ini文件
        在  frameworks\\cocos2d-x\\tools\\tolua 中,复制一份该文件夹下cocos2dx.ini的配置信息,然后修改一些参数,改成我们自定义类的参数。
Lua ——Cocos之_Lua调用C++类

文章图片

        以下列出需要修改的参数配置:

[custom_api]#  prefix会被添加到生成的函数.你也可以选择不添加这个到你的模板 prefix  =  custom_api#  所有的类都会嵌入到这个命名空间 target_namespace  =  my#  类所在的路径,如果有多个,用空格隔开 headers  =  %(cocosdir)s/../runtime-src/Classes/PanZoomLayer.h#  需要注册的类,如果有多个,用空格隔开 classes  =  PanZoomLayer#  不提供给Lua的public成员函数 skip  =  PanZoomLayer::[onTouchesBegan  onTouchesMoved  onTouchesEnded  init  onEnter  onExit  update]#  这些全空就好了 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\\tolua 的  genbindings.py  中的129行找到  cmd_args 。
        将我们自定义的  custom_api.ini 添加进去,并注释掉其他.ini(这些已经不需要重新生成)
Lua ——Cocos之_Lua调用C++类

文章图片



4、运行  genbindings.py 脚本
        在终端运行  genbindings.py 脚本。
        在这里,我是直接写了一个批处理文件 .bat 。
        注意:只要需要用到的工具都下载,安装,配置好了,一般就能生成成功。

                        生成失败的,基本都是因为工具没有配置好。

Lua ——Cocos之_Lua调用C++类

文章图片



        生成成功后,在  frameworks\\cocos2d-x\\cocos\\scripting\\lua-bindings\\auto 中会找到我们生成的C++的桥接文件, lua_custom_api_auto.cpp 和 lua_custom_api_auto.hpp 。
Lua ——Cocos之_Lua调用C++类

文章图片



        其中 lua_custom_api_auto.hpp 中的  register_all_custom_api 就是我们用来将PanZoomLayer类注册到Lua环境中的关键函数。
Lua ——Cocos之_Lua调用C++类

文章图片



        以及在  frameworks\\cocos2d-x\\cocos\\scripting\\lua-bindings\\auto\\api 中也能够找到我们提供给Lua调用的接口文件。
Lua ——Cocos之_Lua调用C++类

文章图片



5、编译注册到Lua

        注册自定义类的函数在我们的  lua_custom_api_auto.hpp 中可以看到。
                register_all_custom_api(lua_State* tolua_S)

Lua ——Cocos之_Lua调用C++类

文章图片



        使用 VS2013 打开  frameworks\\runtime-src\\proj.win32 下的工程。
    (1)将自定义的类 PanZoomLayer 添加到项目工程的Classes下。
Lua ——Cocos之_Lua调用C++类

文章图片

        (2)将  lua_custom_api_auto.cpp、lua_custom_api_auto.hpp  添加到工程liblua的auto下。
Lua ——Cocos之_Lua调用C++类

文章图片

        (3)添加lualib工程的文件搜索路径。

                将  $(EngineRoot)../runtime-src/Classes 路径加进去。
Lua ——Cocos之_Lua调用C++类

文章图片

    (4)编辑  frameworks\\runtime-src\\Classes 下的入口类 AppDelegate.cpp
                >   添加:lua_custom_api_auto.hpp  头文件

Lua ——Cocos之_Lua调用C++类

文章图片

                > 注册:register_all_custom_api(state)

                > 注意:register_all_custom_api 的上下两句话,必须加上!
Lua ——Cocos之_Lua调用C++类

文章图片

       
        (5)编译运行整个项目,完成C++类的注册到Lua。
                然后就可以再Lua中愉快的使用自定义的类了!





【开启智能提示】
        虽然我们将我们自定义的C++类注册到了Lua中调用,但是在Cocos Code IDE中却没有我们自定义类的智能提示。

        我们需要修改一些配置,让Cocos Code IDE加上对我们自定义类的智能提示。



1、Cocos2dx引擎中的智能提示
        首先我们来看一下Cocos Code IDE中cocos2dx引擎的智能提示是怎么搞的。
        随便找个 cc.Label 把!

        我们按住键盘的 ctrl 键,然后点击 cc 和 Label,就会跳转到声明它们的地方。

Lua ——Cocos之_Lua调用C++类

文章图片

    文件跳转到了如下两幅图的地方:
Lua ——Cocos之_Lua调用C++类

文章图片



Lua ——Cocos之_Lua调用C++类

文章图片



        可能看到以上两幅图,你就明白应该怎么给我们自定义的C++类加上智能提示了吧?


        我们先找到以下文件路径:(可能每个人的不一样)

        \\CocosCodeIDE\\configuration\\org.eclipse.osgi\\bundles\\61\\1\\.cp\\resource\\cocos2dx-3.2
    可以发现该路径下有一个 api.zip 这个压缩包。
        我们将其 api.zip 解压出来看看里面都是什么东西。
Lua ——Cocos之_Lua调用C++类

文章图片

Lua ——Cocos之_Lua调用C++类

文章图片



Lua ——Cocos之_Lua调用C++类

文章图片



        可以发现里面全是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 代码如下:

-------------------------------- --  @module  my-------------------------------------------------------- --  the  my  PanZoomLayer --  @field  [parent=#my]  PanZoomLayer#PanZoomLayer  PanZoomLayer  preloaded  modulereturn  nil



Lua ——Cocos之_Lua调用C++类

文章图片



        PanZoomLayer.lua 代码如下:
Lua ——Cocos之_Lua调用C++类

文章图片



        然后我们将 my.lua 和  PanZoomLayer.lua 一并压缩到 myapi.zip 中。
        就放在  \\frameworks\\cocos2d-x\\cocos\\scripting\\lua-bindings\\auto\\api 中好了。
Lua ——Cocos之_Lua调用C++类

文章图片



        然后我们打开Cocos Code IDE的工程项目,配置属性。

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

        将我们的 myapi.zip 压缩包添加进去,点击“确定”。

Lua ——Cocos之_Lua调用C++类

文章图片



        这样,就可以在 Cocos Code IDE 中愉快的玩我们自定义的类了。

        有智能提示,就是爽啊!!!
Lua ——Cocos之_Lua调用C++类

文章图片


Lua ——Cocos之_Lua调用C++类

文章图片

Lua ——Cocos之_Lua调用C++类

文章图片

Lua ——Cocos之_Lua调用C++类

文章图片



3、添加智能提示(方式二)
        通过上面的方式一的方法虽然可以有智能提示,可是后来我发现定义的命名空间 my 却无法识别。这样的结果将导致创建的 my.PanZoomLayer:create() 赋值给 self 的成员 self.pzLayer 后,继续使用  self.pzLayer 时,对应的函数又无法提示了。
Lua ——Cocos之_Lua调用C++类

文章图片

        所以这里我们通过修改官方智能提示包 api.zip ,来达到更加的智能提示的效果。

        操作方法和方式一类似,我们先将官方的提示包 api.zip 解压出来,最好将其备份一份。

        文件在:
        \\Cocos Code IDE\\configuration\\org.eclipse.osgi\\bundles\\61\\1\\.cp\\resource\\cocos2dx-3.2
Lua ——Cocos之_Lua调用C++类

文章图片



        然后我们将我们自定义提示包 my.lua 和 PanZoomLayer.lua 放入 api 文件夹中。

Lua ——Cocos之_Lua调用C++类

文章图片



        然后在 api 文件夹中找到 global.lua 这个全局声明文件。

        将我们自定义的命名空间 my 声明进去。

--  the  my  module --  @field  [parent=#global]  my#my  my  preloaded  module



Lua ——Cocos之_Lua调用C++类

文章图片



        保存关闭,将 api 文件夹压缩成 api.zip 包。

Lua ——Cocos之_Lua调用C++类

文章图片

       
        然后刷新我们的项目工程,然后再来试试我们自定义类的智能提示效果。

        可以发现,自定义的类的智能提示已经和 官方的智能提示功能 完全一致了。

        又可以愉快的玩耍啦!!!
Lua ——Cocos之_Lua调用C++类

文章图片

Lua ——Cocos之_Lua调用C++类

文章图片





【遇到的问题】


1、脚本生成出错
Lua ——Cocos之_Lua调用C++类

文章图片

Lua ——Cocos之_Lua调用C++类

文章图片

       
        这些出错都是由于没有配置  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
Lua ——Cocos之_Lua调用C++类

文章图片



                在  LOCAL_C_INCLUDES 参数的后面添加:(注意后面的  \\  ,仅最后一行不加斜杠)
                        $(LOCAL_PATH)/../../Classes
Lua ——Cocos之_Lua调用C++类

文章图片



        (2)然后配置  frameworks/cocos2d-x/cocos/scripting/lua-bindings/Android.mk文件。
                在  LOCAL_SRC_FILES 参数的后面添加:(注意后面的  \\  ,仅最后一行不加斜杠)
                        auto/lua_custom_api_auto.cpp
Lua ——Cocos之_Lua调用C++类

文章图片



                在  LOCAL_C_INCLUDES 参数的后面添加:(注意后面的  \\  ,仅最后一行不加斜杠)
                        $(LOCAL_PATH)/../../../../runtime-src/Classes
Lua ——Cocos之_Lua调用C++类

文章图片



        (3)然后 Build-Runtime,将项目在Android端编译一下。

Lua ——Cocos之_Lua调用C++类

文章图片



        (4)若编译成功,就可以在Android手机上测试了!





【Lua ——Cocos之_Lua调用C++类】


    推荐阅读