我所理解cocos2d-x 3.6 lua -- Cocos如何绑定Lua自定义类

cocos2d-x 2.x 与 cocos2d-x 3.x 差异(tolua++)


cocos2d-x在2.x版本里就是用toLua++和.pkg文件这么把自己注册进Lua环境里的,然而从cocos2d-x 3.x开始,用bindings-generator脚本代替了toLua++。


bindings-generator脚本的工作机制是:
1、不用编写.pkg和.h文件了,直接定义一个 ini 文件 注册到Lua环境 里的模块名是什么,就行了。
2、摸清了toLua++工具的生成方法,改由Python脚本动态分析C++类,自动生成桥接的.h和.cpp代码,不调用tolua++命令了

3、虽然不再调用tolua++命令了,但是底层仍然使用toLua++的库函数,比如tolua_function,bindings-generator脚本生成代码就跟使用toLua++工具生成的几乎一样


bindings-generator脚本掌握了生成toLua++桥接代码的主动权,不仅可以省下大量的.pkg和.h文件,而且可以更好地插入自定义代码,达到cocos2d-x环境下的一些特殊目的,比如内存回收之类的,所以cocos2d-x从3.x开始放弃了toLua++和.pkg而改用了自己写的bindings-generator脚本是非常值得赞赏的聪明做法。

接下来说怎么用bindings-generator脚本:
1、写自己的C++类,按照cocos2d-x的规矩,继承cocos2d::Ref类,以便使用cocos2d-x的内存回收机制。
2、编写一个.ini文件,让bindings-generator可以根据这个配置文件知道C++类该怎么暴露出来
3、修改bindings-generator脚本,让它去读取这个.ini文件
4、执行bindings-generator脚本,生成桥接C++类方法
5、用VS2012将自定义的C++类和生成的桥接文件加入工程,不然编译不到
6、修改AppDelegate.cpp,执行桥接方法自定义的C++类就注册进Lua环境里了。

首先是自定义的C++类。我习惯将文件保存在 frameworks/runtime-src/Classes/ 目录下:

frameworks/runtime-src/Classes/MyClass.h

  1. #include"cocos2d.h"
  2. usingnamespacecocos2d;
  3. classMyClass:publicRef
  4. {
  5. public:
  6. MyClass(){};
  7. ~MyClass(){};
  8. boolinit(){returntrue;};
  9. CREATE_FUNC(MyClass);
  10. intfoo(inti);
  11. };
frameworks/runtime-src/Classes/MyClass.cpp

copy
    #include"MyClass.h"
  1. intMyClass::foo(inti)
  2. returni+100;
  3. }
然后编写.ini文件。在frameworks/cocos2d-x/tools/tolua/目录下能看到genbindings.py脚本和一大堆.ini文件,这些就是bindings-generator的实际执行环境了。随便找一个内容比较少的.ini文件,复制一份,重新命名为MyClass.ini。大部分内容都可以凑合不需要改,这里仅列出必须要改的重要部分:
frameworks/cocos2d-x/tools/tolua/MyClass.ini

copy
    [MyClass]
  1. prefix=mineClass#添中前缀名XX,注册文件头及注册函数名以前缀名(XX)组合命名
  2. target_namespace=my#空间命名,调用时,以my.xxx,xxx为自定义类的方法
  3. headers=%(cocosdir)s/../runtime-src/Classes/MyClass.h#获取自定义类的文件
  4. classes=MyClass#需要注册类YY(方法),同时注册函数名以前缀名(XX)_YY组合命名
frameworks/cocos2d-x/tools/tolua/genbindings.py
copy
    cmd_args={'cocos2dx.ini':('cocos2d-x','lua_cocos2dx_auto'),\
  1. 'MyClass.ini':('MyClass','lua_MyClass_auto'),\
  2. ...
(其实这一步本来是可以省略的,只要让genbindings.py脚本自动搜寻当前目录下的所有ini文件就行了,不知道将来cocos2d-x团队会不会这样优化)
至此,生成桥接文件的准备工作就做好了,执行genbindings.py脚本:

copy
    pythongenbindings.py
成功执行genbindings.py脚本后,会在frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/目录下看到新生成文件



注:若Python报错,看下是否缺少yaml、Cheetah包,若是,安装包就行了。

简单解释下编译成后lua_MyClass_auto.cpp

copy
    TOLUA_APIintregister_all_mineClass(lua_State*tolua_S)
  1. //入口点,它创建管理的内部变量
  2. tolua_open(tolua_S);
  3. //创建新模块
  4. tolua_module(tolua_S,"my",0);
  5. //注册一个模块或类
  6. tolua_beginmodule(tolua_S,"my");
  7. //类的注册
  8. lua_register_mineClass_MyClass(tolua_S);
  9. tolua_endmodule(tolua_S);
  10. return1;
  11. 注册类:

    copy
      intlua_register_mineClass_MyClass(lua_State*tolua_S)
    1. tolua_usertype(tolua_S,"MyClass");//注册用户类型
    2. tolua_cclass(tolua_S,"MyClass","MyClass","cc.Ref",nullptr);//注册
    3. //注册模块
    4. tolua_function(tolua_S,"new",lua_mineClass_MyClass_constructor);//绑定函数(将Lua里面MyClass对象的”new”绑定到你的lua_mineClass_MyClass_constructor()函数中去.)
    5. tolua_function(tolua_S,"init",lua_mineClass_MyClass_init);
    6. ottom:none; border-left:3px solid rgb(108,"foo",lua_mineClass_MyClass_foo);
    7. ottom:none; border-left:3px solid rgb(108,"create",lua_mineClass_MyClass_create);
    8. tolua_endmodule(tolua_S);
    9. std::stringtypeName=typeid(MyClass).name();//保存注册
    10. g_luaType[typeName]="MyClass";
    11. g_typeCast["MyClass"]="MyClass";
    12. 绑定函数,要注意下:

      copy
        cobj=(MyClass*)tolua_tousertype(tolua_S,1,0);//是将数据栈下的对象以(CTest*)的指针形式弹出来。
      从栈中弹出对象(其实是自定类的对象),接着把对象引用方法(包括含参数及handle)返回结果压栈,实现c、lua之间互相调用了。


      2.编译运行

      打开Classes/lua_module_register.h文件添加文件

      copy
        #include"tolua++/lua_MyClass_auto.hpp"
      在static int lua_module_register(lua_State* L)添加注册函数

      copy
        register_all_mineClass(L);
      若vs2012编译错误,估计都是没把源文件生成文件加入工程; 若有特殊处理,比如更换genbindings.py脚本生成文件路径,注意在vs2012环境->属性->c/c++->附加包含目录,添加路径。

      lua代码

      copy
        functionmyadd(x,y)
      1. --自定义
      2. localtest=my.MyClass:create()
      3. print("luabind:"..test:foo(99))
      4. returnx+y
      5. end
      编译运行:





      -----------------------------------------------------------------------------------------------------------------------------
      本文转自:http://blog.csdn.net/rexuefengye/article/details/46553239

      相关文章

          本文实践自 RayWenderlich、Ali Hafizji 的文章《...
      Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
      第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
          Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
      1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
         Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...