Cocos2dx-JS绑定C++大致流程
Cococs2dx-JS 版本3.12,环境:Mac
。这里有两种情况,为修改引擎底层方法和自定义新的C++类。
首先为了保证genbindings.py 正常运行 你需要下3样东西 已安装的请略过
- python 2.7.x:目前引擎里面的bindings-generator只支持python2.7.x版本
- py-ymal(http://pyyaml.org/wiki/PyYAML):这是python的一个第三方包,下载页有不同系统的安装方式,可以参考generator.py会调用到这个包。
- cheetah(http://www.cheetahtemplate.org/):这也是python的一个第三方包,一个模板,generator.py会调用到这个包.
安装目录执行 python setup.py install 进行安装.
修改引擎底层方法
这个比较简单,这里做的是给UIImageView添加了一个public方法。然后在js中用一个UIImageView对象去调用这个方法。
首先在UIImageView.cpp中添加如下方法:
void ImageView::getImageDes()
{
CCLOG("this is getImageDes!!");
}
然后到工程/frameworks/cocos2d-x/tools/tojs目录下执行python脚本genbindings.py。(可以对这个脚本修改,然后只是重新绑定UIImageView相关的文件)。然后就可以在/frameworks/cocos2d-x/cocos/scripting/js-bindings/auto目录下的jsb_cocos2dx_ui_auto.cpp文件中看到相应的绑定内容。如下:
bool js_cocos2dx_ui_ImageView_getImageDes(JSContext *cx, uint32_t argc, jsval *vp)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::RootedObject obj(cx, args.thisv().toObjectOrNull());
js_proxy_t *proxy = jsb_get_js_proxy(obj);
cocos2d::ui::ImageView* cobj = (cocos2d::ui::ImageView *)(proxy ? proxy->ptr : NULL);
JSB_PRECONDITION2( cobj, cx, false, "js_cocos2dx_ui_ImageView_getImageDes : Invalid Native Object");
if (argc == 0) {
cobj->getImageDes();
args.rval().setUndefined();
return true;
}
JS_ReportError(cx, "js_cocos2dx_ui_ImageView_getImageDes : wrong number of arguments: %d, was expecting %d", argc, 0);
return false;
}
然后在js脚本中就可以调用getImageDes方法了,如下:
this._image.getImageDes();
控制台就可以看到打印。这种方式还是比较简单的绑定。
添加自定义的C++类
这里我创建了一个简单的C++类,CustomClass:
CustomClass.h
#ifndef CUSTOMCLASS
#define CUSTOMCLASS
#include "cocos2d.h"
namespace cocos2d {
class CustomClass : public cocos2d::Ref
{
public:
CustomClass();
~CustomClass();
bool init();
std::string helloMsg();
CREATE_FUNC(CustomClass);
};
} //namespace cocos2d
#endif // CUSTOMCLASS
CustomClass.cpp
#include "CustomClass.h"
USING_NS_CC;
CustomClass::CustomClass(){
}
CustomClass::~CustomClass(){
}
bool CustomClass::init(){
return true;
}
std::string CustomClass::helloMsg(){
return "this is CustomClass Msg!";
}
然后把这个类放在游戏工程目录/frameworks/cocos2d-x/cocos/my/下。
file.png
然后把my文件夹导入到cocos2d_libs工程中,
structure.png
并为cocos2d_libs工程的 User Header Searcher Paths,添加目录,指定到my目录下,$(SRCROOT)/../../../../cocos/my。
同时,我也为游戏工程添加了这个目录(这个觉得是没有必要的)。
然后在tojs文件夹下添加cocos2dx_custom.ini文件。这个可以复制一份,然后修改相应的位置,主要是
headers = %(cocosdir)s/cocos/my/CustomClass.h 这个是头文件的路径,然后是
classes = CustomClass.* 这个是要包含进来的类
classes_need_extend = CustomClass 需要在js里面派生的类
然后修改 genbindings.py这个文件,151行的位置,添加刚才的cocos2dx_custom.init文件,如下:
cmd_args = {'cocos2dx.ini': ('cocos2d-x', 'jsb_cocos2dx_auto'),
'cocos2dx_custom.ini': ('cocos2dx_custom', 'jsb_cocos2dx_custom_auto'),
}
这是一份完整的cocos2dx_custom.ini:
[cocos2dx_custom]
# the prefix to be added to the generated functions. You might or might not use this in your own
# templates
prefix = cocos2dx_custom
# 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 = ccext
android_headers = -I%(androidndkdir)s/platforms/android-19/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/%(clang_version)s/include
clang_flags = -nostdinc -x c++ -std=c++11 -U __SSE__
cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos -I%(cocosdir)s/cocos/base -I%(cocosdir)s/cocos/platform/android -I%(cocosdir)s/extensions -I%(cocosdir)s/external -I%(cocosdir)s/cocos/editor-support -I%(cocosdir)s/cocos/network -I%(cocosdir)s/cocos/ui/UIEditBox -I%(cocosdir)s/cocos/ui -I%(cocosdir)s/jsext -I%(cocosdir)s/jsext/system -I%(cocosdir)s/jsext/alipay -I%(cocosdir)s/jsext/video -I%(cocosdir)s/jsext/webview -I%(cocosdir)s/jsext/umeng
#cocos_headers = -I%(cocosdir)s -I%(cocosdir)s/cocos -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 = %(cocosdir)s/cocos/extra/CustomClass.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 = CustomClass.*
#需要在js里面派生的类
#classes_need_extend = CustomClass
# 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 = Ref
# 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
剩下的就是运行 python genbindings.py,绑定成功之后可以在项目/frameworks/cocos2d-x/cocos/scripting/js-bindings/auto目录下看到对应的jsb_cocos2dx_custom_auto.hpp和jsb_cocos2dx_custom_auto.cpp,同时在这个目录下有一个api文件夹,jsb_cocos2dx_custom_api.js也相应的生成了。
然后把这两个文件导入到cocos2d_js_bindings工程的auto文件夹下。
jsb_binding_structure.png
然后在AppDelegate.cpp文件中注册,如下:
//jsbinding test
sc->addRegisterCallback(register_all_cocos2dx_custom);
然后我们就可以在js代码中使用我们的C++类了
var customClass = ccext.CustomClass.create();
var msg = customClass.helloMsg()
cc.log("customClass's msg is========>>>" + msg)
此时可以在控制台看到打印log。至此,js绑定C++已经完成 。
然后就是 Android 下面的处理。主要是把我们新添加的类,包含到Android.mk中。首先到项目/frameworks/cocos2d-x/cocos/scripting/js-bindings/proj.android/目录下,找到Android.mk ,然后在 LOCAL_C_INCLUDES下,包含我们的新添加的类的路径。在 LOCAL_SRC_FILES下包含,我们的cpp文件,如下: ../auto/jsb_cocos2dx_custom_auto.cpp \
。同时,要保证我们的原始的C++类也包含到mk文件中,保证变异的时候能找到我们的原始C++文件。然后这样Android下面编译也没什么问题了。