Js 调用 c++ 代码的方法

前言: 最近搞js 各种不方便 能用js的解决的麻烦也用js解决了 有些引擎问题实在得用c++ 讨教一个做过js的哥们 发我一个手绑的文档 各种绑定看着就头大 后来看一篇残缺的文章原来这些都是自动生成的.研究半天 发现自动绑定还是很easy的 下面就简单讨论一下:

首先为了保证genbindings.py 正常运行 你需要下3样东西 已安装的请略过
1.python 2.7.x:目前引擎里面的bindings-generator只支持python2.7.x版本
2.py-ymal(http://pyyaml.org/wiki/PyYAML):这是python的一个第三方包,下载页有不同系统的安装方式,可以参考generator.py会调用到这个包。
3.cheetah(http://www.cheetahtemplate.org/):这也是python的一个第三方包,一个模板,generator.py会调用到这个包.

PS: 安装目录执行 python setup.py install 进行安装 下载页面有安装方法

下面说一下第一种情况比较简单 就是 添加修改底层引擎方法

例如 我想取得一些骨骼坐标做参考点 使用 ccs.Armature 的 getBone(name).getWorldInfo(); 遇到问题 js 数据get 不到 看C++ 代码又是完全正确的 而且c++输出也是正确的 所以不再深究 直接在添加一个取坐标的方法完事

我们打开 项目->frameworks->runtime-src 下面的源代码工程文件 (如果没有frameworks文件夹 在cocoside 项目右键 cocos工具->添加本地代码支持 或者 构建一个模拟器即可)

在 CCBone 下添加如下方法

cocos2d::Point Bone::getPos() const
{
return cocos2d::Point(_worldInfo->x,_worldInfo->y);
}

然后 到 项目->tools->tojs 下 python genbindings.py

我们可以看到 jsb_cocos2dx_studio_auto.hpp 中 多了绑定函数!

ok 至此 我们就可以用 刚才在CCBone里面添加的新函数 getBone(name).getPos() 了! 就是这么简单 全自动 自己不用在照着例子粘贴函数了!

下面介绍一下 自己新添加一个C++类 如何绑定到js!

我们建立自己要绑定的类

测试用的代码很好懂
// CustomClass.h

#ifndef __CUSTOM__CLASS

#define __CUSTOM__CLASS

#include “cocos2d.h”

namespace cocos2d {
class CustomClass : public cocos2d::Ref
{
public:

CustomClass();

~CustomClass();

bool init();

std::string helloMsg();

CREATE_FUNC(CustomClass);

};
} //namespace cocos2d

#endif // __CUSTOM__CLASS

// CustomClass.cpp
#include “CustomClass.h”

USING_NS_CC;

CustomClass::CustomClass(){

}

CustomClass::~CustomClass(){

}

bool CustomClass::init(){
return true;
}

std::string CustomClass::helloMsg() {
return “Hello from CustomClass::sayHello”;
}

用xcdoe 打开 frameworks/runtime-src/proj.ios_mac/CocosJSGame.xcodeproj 添加 自己的文件 (windows VS党 后面的仅供参考…)

注意俩个lib 都勾选上!
添加后

选中 cocos2d_js_bindings.xcodeproj 添加刚才的引用路径

下面的也要添加

然后再 项目->tools->tojs 目录下 新建 cocos2dx_custom.ini 文件

复制如下内容

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 = cc

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

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

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/my/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.*

what should we skip? in the format ClassName::

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 Clonable

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

注意 其中

headers = %(cocosdir)s/cocos/my/CustomClass.h

classes = CustomClass.*

名字要改成 自己要添加的类名
其中 还有一些配置 例如跳过某些类方法 skip = 等等 大家可以自己研究官方的 ini文件

打开 tools/tojs/genbindings.py

在 custom_cmd_args 添加 ‘cocos2dx_custom.ini’ : (‘cocos2dx_custom’, ‘jsb_cocos2dx_custom’), \

修改完成如下

custom_cmd_args = {
‘cocos2dx_custom.ini’ : (‘cocos2dx_custom’, ‘jsb_cocos2dx_custom’),
}

接下来运行 python genbindings.py 等待成功!

完事以后会生成你自己 hpp 和 cpp 以及 js api

用Xcode打开 项目 如果没有 jsb_cocos2dx_custom.hpp 和 jsb_cocos2dx_custom.cpp 就添加以下 记得 mac ios lib 都要勾选上

此时恭喜你已经大功告成!

打开AppDelegate.cpp 添加 addRegisterCallback(register_all_cocos2dx_custom) 进行注册


#include “jsb_cocos2dx_custom.hpp”

sc->addRegisterCallback(register_all_cocos2dx_custom);

#if (COCOS2D_DEBUG>0)
if (startRuntime())
return true;
#endif

ScriptingCore::getInstance()->start();

在js中调用
var customClass = cc.CustomClass.create();

var msg = customClass.helloMsg()

cc.log("customClass’s msg is : " + msg)

输出 customClass’s msg is : Hello from CustomClass::sayHello

就此自动绑定C++类 完毕! 有什么问题欢迎大家讨论!

不知道怎么截图都没了…用下官方原帖的图吧.

楼主,我照着做了,可是绑定过程中出错了,前面几个都绑定过了,到cocos2dx_custom的时候,就绑定出错了。错误信息就是下图。

错误的截图

补充一下 添加的新 c++ 类 打安卓包时会提示找不到文件路径 需要把 \frameworks\js-bindings\cocos2d-x\cocos\Android.mk 和 \frameworks\js-bindings\bindings\Android.mk 里面配置上相关路径

:12: 我昨天才刚刚搞一次,我发现自己安装pytaml盒cheetah是错误的:10:就是你虽然装上去了但是仍然说yaml不存在

后来我发现按照下面的步骤安装才正确又方便
打开tools/tojs/README.mdown 按照里面的说明逐次运行
sudo easy_install pip
sudo pip install PyYAML
sudo pip install Cheetah

:12: :12: 楼主能不能出一个framwork3.7的绑定,目前我仍未能搞定

这不是以前官方的吗.说了等于没说一样.这个教程.就是误导人的.

3.7 以上能定制 framwork 了 去商店下载 framwork 3.7 安装 在 应用程序->cocos->frameworks 会有 3.7 frameworks 工程 用 xcdoe 打开能很方便 定制自己frameworks 但不过 我用 1.2的ide 不知道为啥打包不太对… 我是 3.7新建一个 同名空项目 把 frameworks 拷贝过去 在 1.2ide 里面生成一遍 配置一下模拟器路径 再把 以前 的tool/tojs/genbindings.py 替换进来就可以 现在1.2的IDE 升级到 3.7.1了 没有任何问题

绑定需要继承的类怎么配置

反过来c++调用js的方法有么,在3.10 中使用,没有成功调用