• Lua调用自定义C++类


    本节要讲的是如何将自己写的C++类注册进Lua环境,让Lua去调用自定义的C++类。网上有很多都是用原始的tolua++工具来注册C++类的,我看了很多这样的教程,感觉操作起来十分麻烦,而且也很难看懂他们到底在讲什么。

    其实,在Cocos2d-x 3.2版本中,提供了bindings-generator脚本来封装toLua++的用法,从而节省了工作量。

    【使用工具】

    • Windows7 x64

    • Cocos2d-x 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的安装目录Libsite-packages"(点击下载

    • Cheetah,并解压到 "Python的安装目录Libsite-packages"(点击下载

    • dos2unix,windows下可能在执行脚本时有这个错误。解压到一某个目录下面, 并设置PATH环境变量的值指向bin目录下。(点击下载

    【绑定方法】

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

    并使用Cocos Code IDE创建的Lua项目,绑定方法。

    1、将自定义的C++代码放在frameworks untime-srcClasses下

    当然放哪里是随意的,我喜欢放在Classes下。

    1414394105901015.jpg

    2、添加自定义类的.ini文件

    在 frameworkscocos2d-x ools olua 中,复制一份该文件夹下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::[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

    在 frameworkscocos2d-x ools olua 的 genbindings.py 中的129行找到cmd_args。

    将我们自定义的 custom_api.ini 添加进去,并注释掉其他.ini(这些已经不需要重新生成)

    1414394201736120.jpg

    4、运行 genbindings.py 脚本

    在终端运行 genbindings.py 脚本。

    在这里,我是直接写了一个批处理文件 .bat 。

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

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

    1414394239287445.jpg

    生成成功后,在 frameworkscocos2d-xcocosscriptinglua-bindingsauto 中会找到我们生成的C++的桥接文件, lua_custom_api_auto.cpp 和 lua_custom_api_auto.hpp 。

    wKioL1RL2y6DVRX7AAB3H2ztpRw355.jpg

    其中,lua_custom_api_auto.hpp 中的 register_all_custom_api 就是我们用来将PanZoomLayer类注册到Lua环境中的关键函数。

    1414394321915510.jpg

    以及在 frameworkscocos2d-xcocosscriptinglua-bindingsautoapi 中也能够找到我们提供给Lua调用的接口文件。

    1414394347801423.jpg

    5、编译注册到Lua

    注册自定义类的函数在我们的 lua_custom_api_auto.hpp 中可以看到。

    register_all_custom_api(lua_State* tolua_S)

    1414394385791213.jpg

    使用 VS2013 打开 frameworks untime-srcproj.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 路径加进去。

    1414394438262374.jpg

    (4)编辑 frameworks untime-srcClasses 下的入口类 AppDelegate.cpp

    • 添加:lua_custom_api_auto.hpp 头文件

    wKiom1RL3Lug2Np1AAAqi0a-IYQ249.jpg

    注册:register_all_custom_api(state)

    注意:register_all_custom_api 的上下两句话,必须加上!

    1414394634729469.jpg

    (5)编译运行整个项目,完成C++类的注册到Lua。

    然后就可以再Lua中愉快的使用自定义的类了!

    【开启智能提示】

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

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

    1、Cocos2d-x引擎中的智能提示

    首先我们来看一下Cocos Code IDE中cocos2dx引擎的智能提示是怎么搞的。

    随便找个 cc.Label 把!

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

    wKiom1RL4vGjjv10AAAi5Dt7P4A782.jpg

    文件跳转到了如下两幅图的地方:

    1414394830959144.jpg

    1414394844858986.jpg

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

    我们先找到以下文件路径:(可能每个人的不一样)CocosCodeIDEconfigurationorg.eclipse.osgiundles611.cp esourcecocos2dx-3.2

    可以发现该路径下有一个 api.zip 这个压缩包。

    我们将其 api.zip 解压出来看看里面都是什么东西。

    1414394913337354.jpg

    1414394927635338.jpg

    1414394943211161.jpg

    可以发现里面全是cocos2dx的C++类提供给Lua的接口声明。

    这些也就是IDE中智能提示的原因。

    2、添加自定义类的智能提示(方式一)

    我们仿照 api.zip 中的 cc.lua 和 label.lua 来写一个自定义类的接口声明。

    • my.lua :声明命名空间

    • PanZoomLayer.lua :声明自定义类。(这个在使用脚本绑定时,自动生成)

    其中 PanZoomLayer.lua 在使用 genbindings.py 脚本时,就自动生成了的。

    就在 frameworkscocos2d-xcocosscriptinglua-bindingsautoapi 中。

    那么,我们再写一个 my.lua ,也放在这个目录下好了。

    其中,my.lua 代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    --------------------------------
     
    -- @module my
     
    --------------------------------------------------------
     
    -- the my PanZoomLayer
     
    -- @field [parent=#my] PanZoomLayer#PanZoomLayer PanZoomLayer preloaded module
     
    return nil

    1414395010397599.jpg

    PanZoomLayer.lua 代码如下:

    1414395025424719.jpg

    然后我们将 my.lua 和 PanZoomLayer.lua 一并压缩到 myapi.zip 中。

    就放在 frameworkscocos2d-xcocosscriptinglua-bindingsautoapi 中好了。

    wKioL1RL6wPiJgirAAEhY5DYprw732.jpg

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

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

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

    1414395075543177.jpg

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

    有智能提示,就是爽啊!!

    1414395112572279.jpg

    1414395124998961.jpg

    1414395137381872.jpg

    3、添加智能提示(方式二)

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

    wKiom1RMtE6xkHlyAABfA0aiUEs010.jpg

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

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

    文件在:Cocos Code IDEconfigurationorg.eclipse.osgiundles611.cp esourcecocos2dx-3.2

    1414395190344005.jpg

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

    1414395207183418.jpg

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

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

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

    1414395248305601.jpg

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

    1414395266815598.jpg

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

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

    又可以愉快的玩耍啦!!!

    1414395295718581.jpg

    【遇到的问题】

    1、脚本生成出错

    1414395328485740.jpg

    1414395338965517.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

    1414395425285753.jpg

    (2)然后配置 frameworks/cocos2d-x/cocos/scripting/lua-bindings/Android.mk文件。

    在 LOCAL_SRC_FILES 参数的后面添加:(注意后面的 ,仅最后一行不加斜杠)

    auto/lua_custom_api_auto.cpp

    1414395455110139.jpg

    在 LOCAL_C_INCLUDES 参数的后面添加:(注意后面的 ,仅最后一行不加斜杠)

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

    1414395472791025.jpg

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

    wKiom1RL-YTCkK43AAE9zSpAmfo656.jpg

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

  • 相关阅读:
    负载(Load)分析及问题排查
    MySQL 数据库规范--调优篇(终结篇)
    AbstractQueuedSynchronizer
    为什么String被设计为不可变?是否真的不可变?
    数据库 分库 分表 分区
    Oracle 数据库知识汇总篇
    小知识:如何判断数据文件的高水位线
    RHEL7安装11204 RAC的注意事项
    案例:DG主库未设置force logging导致备库坏块
    Oracle 11g RAC之HAIP相关问题总结
  • 原文地址:https://www.cnblogs.com/liuqing0328/p/4763318.html
Copyright © 2020-2023  润新知