|
前言
在游戏开发过程中,主要业务逻辑等由Lua开发(因为可以动态热更、灵活便捷等),但是Lua毕竟是脚本语言,遇到一些高性能需求或其他涉及底层变动,需要用C++来实现(你大爷还是你大爷)。
对于将C++的类或方法导出给Lua调用,
Cocos2d-x引擎采用的是 tolua++,通过便携tolua++的pkg配置文件,来定义要导出的每一个类的信息,这个步骤相当于用tolua++的规则将类的头文件重写成pkg文件,tolua++会根据这个文件以及类的cpp文件来生成C++代码文件。
直接使用tolua++在批量导出的时候会比较麻烦,基于此,引擎提供了 genbindings.py 文件来完成批量导出的工作,流程如下:
编写要导出的C++类为这个类编写一个ini配置文件(一个ini可对应多个类)修改genbindings脚本,加载ini配置执行genbindings脚本,生成类导出到Lua的C++代码将生成的代码添加到项目中,并执行注册方法
本文主要内容一览:
环境搭建使用到的相关配置结构介绍具体实操遇到问题及解决方案
环境搭建
Windows平台
NDK r9b
这里 README上,写的需求版本 r10c or later;但是脚本头部注释要求版本 r9b;经过实际测试使用 r9b 版本NDK 有效。配置环境变量,ndk根目录:NDK_ROOT
Python2.7.3(32bit)
配置环境变量,具体到exe文件:PYTHON_BIN(xxx\python.exe)
Python库 pyyaml
解压或安装到上面python的相应位置: xxx\Lib\site-packages
Python库 pyCheetah
解压或安装到上面python的相应位置: xxx\Lib\site-packages
Mac 平台
待补充
配置介绍
genbindings.py 文件
这个脚本文件主要作用是根据ini文件,执行 cocos2d\tools\bindings-generator\generator.py 来生成导出C++代码。
这个文件需要修改的地方不多,多注意下列几个地方即可:
project_root:项目工程根目录cocos_root:cocos引擎根目录cxx_generator_root:调用的generator.py文件所在的目录tolua_root:tolua根目录,ini配置文件的目录output_dir:导出C++代码的目录cmd_args:需要处理的ini配置文件,如果这次导出不需要,可以用 # 注释
ini 文件配置
ini配置文件主要作用于描述要导出的类,一个ini文件可以配置多个类,一般都以文件夹为单位。
配置文件的结构由三部分组成:
段:一个文件分为多个段;每个段名称用中括号包裹并独占一行键:一个段有多个键;每个键都代表一个配置值:一个键对应任意个值;所有值以空格分隔
例如:- # 注释A
- [sectionA]
- keyA1 =
- keyA2 = valueA2
- keyA3 = valueA3 valueA4
- # 注释B
- [sectionB]
- keyB1 = valueB1
- keyB2 =
复制代码 除了上述配置文件基本规则,还需要注意一些常用且重要的键:
prefix:生成的函数前缀,可能在自建类的模板中用不到,它主要作用应该是做唯一性区分
target_namespace:目标命名空间,lua调用是需要用到,若不填则为全局
headers:要导出的C++类头文件
classes:要导出的Lua类
skip:需要跳过的类方法
不同类间用 逗号 分隔,不同函数名间用 空格 分隔
函数名可以用 正则表达式 ,类名::[set.*],代表跳过所有set开头的函数
若要跳过整个类,可以用 * 代替,类名::
例如:
- skip = ClassA::
- [*], ClassB::[funcNameA funcNameB]
复制代码
rename_functions:可以指定某个类的某个方法以一个新名字导出
不同类间用 逗号 分隔,不同函数名间用 空格 分隔
例如:
- rename_functions = ClassA::[oldFuncNameA=newFuncNameA oldFuncNameB=newFuncNameB], ClassB::[oldFuncNameC=newFuncNameC]
复制代码
还有一些其他键,不是很常用或重要,一般上面都有注释,可以自行分析填写。
结构
genbindings.py 文件 和 ini文件 都是为 generator.py 文件传递配置的。
一般为了将自建的类文件与引擎的区分开,都会新建一个文件夹专门放自建类文件,并与引擎文件同级,同样的导出方法也需要新建一套。
大概结构如下:
实操
修改引擎代码
修改引擎相关代码(路径:xxx\cocos2d)配置相应 ini文件、genbindings 文件(路径:xxx\cocos2d\tools\tolua)执行genbindings脚本(注意用python2.x - 32bit)使用VS编译导出的文件运行游戏验证
创建或修改自建类
修改相关源码
- 配置相应 ini文件、genbindings 文件
- 检查 相应ini文件中是否已经导出了该类
检查 ini文件中 headers 键的值,确定能找到该文件检查 ini文件中 classes 键的值,确定导出了所修改的类检查 ini文件中 skip 键的值,确定所需要导出的类没有被跳过
- 检查 genbindings.py,确定导出配置
检查 genbindings.py 中 cmd_args的值,确定执行相应ini文件
执行genbindings脚本(注意用python2.x - 32bit)使用VS编译导出的文件运行游戏验证
出现问题及解决方案
NDK_ROOT not defined. Please define NDK_ROOT in your environment.
PYTHON_BIN not defined, use current python.
llvm toolchain not found!
路径: “%ndk_root%/toolchains/” , 找不到llvm,检查文件命名;脚本中会先去检查 llvm-3.4,再去查llvm-3.3,保证这两个存在一个就行
‘XX\XX\python’ 不是内部或外部命令,也不是可运行程序
环境变量PYTHON_BIN路径错误,PYTHON_BIN 应该是python2的可执行程序(.exe)
LibclangError: [Error 193] %1 不是有效的 Win32. To provide a path to libclang use Config.set_library_path() or Config.set_library_file().
python库 pyyaml 和 pyCheetah 都用32位版本
自建类的导出代码文件include中不包含文件所属的文件夹
- 主要是由于自建类独立文件夹导致,generator.py 在生成头文件路径的时候,是以引擎为准,所以指定在 xxx/cocos2d/cocos 目录下查找,可见 generator.py 的 search_path 变量:
- 'search_path': os.path.abspath(os.path.join(userconfig.get('DEFAULT','cocosdir'),'cocos')),
复制代码 所以,导出自建类文件的时候,头文件所属的文件夹均忽略了。可见 cocos2d\tools\bindings-generator\targets\lua\templates\layout_head.c- \#include "scripting/lua-bindings/auto/${out_file}.hpp"#if $macro_judgement
- $macro_judgement
- #end if#for header in $headers#set relative = os.path.relpath(header, $search_path)#if not '..' in relative
- \#include "${relative.replace(os.path.sep, '/')}"#else
- \#include "${os.path.basename(header)}"#end if#end for
- \#include "scripting/lua-bindings/manual/tolua_fix.h"
- \#include "scripting/lua-bindings/manual/LuaBasicConversions.h"#if $cpp_headers#for header in $cpp_headers
- \#include "${header}"#end for#end if
复制代码 - 解决:根据之前的结构来看,genbindings.py 是会像 generator.py 传递参数的,我们可以由genbindings根据自己代码源目录指定搜索路径。
在genbindings.py中 添加搜索路径参数:- search_root = os.path.abspath(os.path.join(源文件根目录))
- config.set('DEFAULT','searchdir', search_root)
复制代码 然后再generator.py中不再自行拼接搜索路径,而是使用传递过来的路径:- # 'search_path': os.path.abspath(os.path.join(userconfig.get('DEFAULT', 'cocosdir'), 'cocos')),'search_path': os.path.abspath(os.path.join(userconfig.get('DEFAULT','searchdir'))),
复制代码 至此,兼容了引擎和自建类。
参考资料:
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|