使用cocos2d-x的方式来将C++类注册进Lua环境

2015年03月24日 15:30 0 点赞 0 评论 更新于 2025-11-21 18:28

在Cocos2d-x 2.x版本中,采用toLua++和.pkg文件将自身注册到Lua环境。然而,这种方法存在明显弊端,既需要编写实际功能的.pkg文件,又要编写桥接的.pkg文件和.h文件,工作量大且枯燥。因此,从Cocos2d-x 3.x开始,使用bindings-generator脚本替代了toLua++。

bindings-generator脚本的工作机制

  1. 简化配置文件编写:无需为每个类单独编写桥接的.pkg.h文件,只需定义一个.ini文件,告知脚本哪些类的哪些方法需要暴露,以及注册到Lua环境的模块名。这将原本每个类需要3个文件的工作量,简化为所有类仅需1个.ini文件。
  2. 动态代码生成bindings-generator脚本深入研究了toLua++工具的生成方法,通过Python脚本动态分析C++类,自动生成桥接的.h.cpp代码,不再调用tolua++命令。
  3. 底层库函数复用:虽然不再调用tolua++命令,但底层仍然使用toLua++的库函数,如tolua_functionbindings-generator脚本生成的代码与使用toLua++工具生成的代码几乎相同。

bindings-generator脚本掌握了生成toLua++桥接代码的主动权,不仅节省了大量的.pkg.h文件,还能更好地插入自定义代码,实现Cocos2d-x环境下的特殊目的,如内存回收等。因此,Cocos2d-x从3.x开始放弃toLua++和.pkg,改用bindings-generator脚本是非常明智的选择。

使用bindings-generator脚本的步骤

  1. 编写C++类:按照Cocos2d-x的规范,让自定义的C++类继承cocos2d::Ref类,以便使用Cocos2d-x的内存回收机制。虽然不继承也可以,但不建议这样做,否则在Lua环境下对象的释放会比较麻烦。
  2. 编写.ini文件:编写一个.ini文件,让bindings-generator根据该配置文件了解如何暴露C++类。
  3. 修改脚本配置:修改bindings-generator脚本,使其读取该.ini文件。
  4. 生成桥接代码:执行bindings-generator脚本,生成桥接C++类方法。
  5. 添加到工程:使用Xcode将自定义的C++类和生成的桥接文件添加到工程中,否则无法编译。
  6. 注册到Lua环境:修改AppDelegate.cpp,执行桥接方法,将自定义的C++类注册到Lua环境。

虽然步骤较多,但实际上都很简单,下面将逐步介绍。

编写自定义C++类

习惯将文件保存到frameworks/runtime-src/Classes/目录下。

frameworks/runtime-src/Classes/MyClass.h

#include "cocos2d.h"
using namespace cocos2d;

class MyClass : public Ref
{
public:
MyClass() {};
~MyClass() {};
bool init() { return true; };
CREATE_FUNC(MyClass);

int foo(int i);
};

frameworks/runtime-src/Classes/MyClass.cpp

#include "MyClass.h"

int MyClass::foo(int i)
{
return i + 100;
}

编写.ini文件

frameworks/cocos2d-x/tools/tolua/目录下可以找到genbindings.py脚本和大量的.ini文件,这里是bindings-generator的实际执行环境。可以选择一个内容较少的.ini文件,复制一份并重新命名为MyClass.ini。大部分内容无需修改,仅需修改以下重要部分:

frameworks/cocos2d-x/tools/tolua/MyClass.ini

[MyClass]
prefix = MyClass
target_namespace = my
headers = %(cocosdir)s/../runtime-src/Classes/MyClass.h
classes = MyClass

MyClass.ini中指定MyClass.h文件的位置、要暴露的类以及注册到Lua环境的模块名。

注意:如果.ini配置文件中存在macro_judgement = ...宏定义,需要特别小心。例如,第一次从cocos2dx_controller.ini文件复制时,若未注意macro_judgement,可能导致生成的桥接类文件加入不该加入的宏,使得桥接类仅在iOS和Android平台上起作用,对Mac平台无效。

修改genbindings.py文件

genbindings.py文件的129行附近,将MyClass.ini文件添加进去:

frameworks/cocos2d-x/tools/tolua/genbindings.py

cmd_args = {'cocos2dx.ini': ('cocos2d-x', 'lua_cocos2dx_auto'),
'MyClass.ini': ('MyClass', 'lua_MyClass_auto'),
...

实际上,这一步可以省略,只需让genbindings.py脚本自动搜索当前目录下的所有.ini文件即可,希望未来Cocos2d-x团队能进行这样的优化。

执行脚本生成桥接文件

完成上述准备工作后,执行genbindings.py脚本:

python genbindings.py

在Mac系统上执行时,可能会遇到缺少yamlCheetah包的问题。安装这些Python包很简单,先执行sudo easy_install pip安装pip,然后使用pip searchsudo pip install命令进行安装。