Cocos2d-x 3.6(Lua):Cocos如何绑定Lua自定义C++

看到了一篇文章,讲cocos 3.X lua高版本如何绑定义C++类。文章写的非常好。可惜照他写的做却绑定失败,因为里面一些必然出现的坑作者没有提,可能是时过境迁环境变了,但是必然是绑定失败。这里我援引一下原文章,再把会出现的坑填好。
原文地址

笔者的环境 Quick-Cocos2dx-Community 3.6

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环境里了。

安装必要的库和工具包,以及配置相关环境变量,请按照Quick-Cocos2dx-Community\tools\tolua\README.mdown说得去做,

* Make sure that you have installed `android-ndk-r9b`. 必须是android-ndk-r9b
* Download python2.7.3 (32bit) from (http://www.python.org/ftp/python/2.7.3/python-2.7.3.msi).
* Add the installed path of python (e.g. C:\Python27) to windows environment variable named 'PATH'.
* Download pyyaml from http://pyyaml.org/download/pyyaml/PyYAML-3.10.win32-py2.7.exe and install it.
* Download pyCheetah from https://raw.github.com/dumganhar/my_old_cocos2d-x_backup/download/downloads/Cheetah.zip, unzip it to "C:\Python27\Lib\site-packages"
* Set environment variables (`NDK_ROOT`)

首先是自定义的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文件。在Quick-Cocos2dx-Community\tools\tolua目录下能看到genbindings.py脚本和一大堆.ini文件,这些就是bindings-generator的实际执行环境了。随便找一个内容比较少的.ini文件,如:cocos2dx_spine.ini,复制一份,重新命名为MyClass.ini,我写的如下:
[myclass]
# the prefix to be added to the generated functions. You might or might not use this in your own
# templates
prefix = MineClass

# create a target namespace (in javascript, this would create some code like the equiv. to `ns = ns || {}`)
# all classes will be embedded in that namespace
target_namespace = my

macro_judgement  = #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)

android_headers = -I%(androidndkdir)s/platforms/android-14/arch-arm/usr/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.7/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include -I%(androidndkdir)s/sources/cxx-stl/gnu-libstdc++/4.8/include
android_flags = -D_SIZE_T_DEFINED_ 

clang_headers = -I%(clangllvmdir)s/lib/clang/3.3/include 
clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__

cocos_headers = -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/base -I%(cocosdir)s/cocos/platform/android
cocos_flags = -DANDROID

cxxgenerator_headers = 

# extra arguments for clang
extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s 

# what headers to parse
headers = E:/cocosProj/myluaGame/frameworks/runtime-src/Classes/MyClass.h

# what classes to produce code for. You can use regular expressions here. When testing the regular
# expression, it will be enclosed in "^$", like this: "^Menu*$".
classes = MyClass

# what should we skip? in the format ClassName::[function function]
# ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also
# regular expressions, they will not be surrounded by "^$". If you want to skip a whole class, just
# add a single "*" as functions. See bellow for several examples. A special class name is "*", which
# will apply to all class names. This is a convenience wildcard to be able to skip similar named
# functions from all classes.

skip = 

rename_functions =

rename_classes = 

# for all class names, should we remove something when registering in the target VM?
remove_prefix = 

# classes for which there will be no "parent" lookup
classes_have_no_parents = 

# base classes which will be skipped when their sub-classes found them.
base_classes_to_skip =

# classes that create no constructor
# Set is special and we will use a hand-written constructor
abstract_classes = 

# Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'.
script_control_cpp = no

这里写出要改的部分:

[myclass] #文件标识
prefix = myclass
target_namespace =
headers = E:/cocosProj/myluaGame/frameworks/runtime-src/Classes/MyClass.h #头文件路径
classes = MyClass
skip =
abstract_classes =

我因为没改第一个[myclass] 出错了好久
修改  Quick-Cocos2dx-Community\tools\tolua  下的 genbindings.py,此文件导出的cocos类太多很费时间,最好复制一个,只导自己的类,命名为genbindings_myclass.py
把生成目录制定到咱工程里去,打开genbindings_myclass.py把
?
1
output_dir = '%s/cocos/scripting/lua-bindings/auto' % project_root
 改成
?
1
output_dir = '%s/tests/lua-empty-test/project/Classes/auto' % project_root

修改命令参数,把
?
1
2
3
4
5
6
7
cmd_args = { 'cocos2dx.ini' : ( 'cocos2d-x' , 'lua_cocos2dx_auto' ), \
                    'cocos2dx_extension.ini' : ( 'cocos2dx_extension' , 'lua_cocos2dx_extension_auto' ), \
                    'cocos2dx_ui.ini' : ( 'cocos2dx_ui' , 'lua_cocos2dx_ui_auto' ), \
                    'cocos2dx_studio.ini' : ( 'cocos2dx_studio' , 'lua_cocos2dx_studio_auto' ), \
                    'cocos2dx_spine.ini' : ( 'cocos2dx_spine' , 'lua_cocos2dx_spine_auto' ), \
                    'cocos2dx_physics.ini' : ( 'cocos2dx_physics' , 'lua_cocos2dx_physics_auto' ), \
                    }
    改成
?
1
cmd_args = { 'myclass.ini' : ( 'myclass' , 'lua_myclass_auto' ) }

注意,这时你如果 python genbindings_myclass.py,  必定报错!报libclang找不到的错误。可能是早期版本不兼容所至,需要下载最新的bindings-generator 地址 https://github.com/guojian822/bindings-generator
下载后文件名为 bindings-generator-develop 改名为bindings-generator, 把Quick-Cocos2dx-Community\tools下的bindings-generator替换,最好先备份一下
然后就可以执行 python genbindings_myclass.py,就能生成绑定的桥接类了 lua_MyClass_auto.cpp和lua_MyClass_auto.hpp,把它拷到自己的工程目录下,加入,就像下图那样

编译运行

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

1
#include "tolua++/lua_MyClass_auto.hpp"

在static int lua_module_register(lua_State* L)添加注册函数

1
register_all_MineClass(L);

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

lua代码:

1
2
3
4
5
6
function myadd(x, y)
-- 自定义
local test = my.MyClass:create()
print( "lua bind: "  .. test:foo(99))
return  x + y
end

编译运行:


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值