Cocos2d-js JSB绑定学习笔记
来源:互联网 发布:河源优化公司 编辑:程序博客网 时间:2024/05/16 09:44
cocos2d js 的jsb绑定简单来讲就是在C++底层实现一些类库,然后经过一些特定处理可以在js端进行调用的方法。此文档用于记录手动绑定C++自定义类库到js端的实现过程。
此jsb绑定基于cocos2d-js 3.6.1测试使用。
————————————————朴实无华分割线,以上内容不重要————————————————
1、向自定义的JSB绑定目录JSBCustom添加一个需要绑定的JSBClass类
JSBClass.h文件内容如下:
#pragma once#include "cocos2d.h"#include <string>USING_NS_CC;namespace jsbcustom{ void globalFunc_jsbTest(); class JSBClass : public Ref { public: JSBClass(); CREATE_FUNC(JSBClass); virtual bool init(); void jsbTestShow(std::string info); int jsbTestGetInt(); void jsbTestCallBack(std::function<void(int)> callback); };}
JSBClass.cpp文件内容如下:
#include "JSBClass.h"void jsbcustom::globalFunc_jsbTest(){ log("imcustom::globalFunc_jsbTest call!!!");}jsbcustom::JSBClass::JSBClass(){ log("jsbcustom::JSBClass::JSBClass call!!!");}bool jsbcustom::JSBClass::init(){ log("jsbcustom::JSBClass::init call by create!!!"); return true;}void jsbcustom::JSBClass::jsbTestShow(std::string info){ log("jsbcustom::JSBClass::jsbTestShow call, show parameter = %s!!!",info.c_str());}int jsbcustom::JSBClass::jsbTestGetInt(){ log("jsbcustom::JSBClass::jsbTestGetInt call,return test value 73!!!"); return 73;}void jsbcustom::JSBClass::jsbTestCallBack(std::function<void(int)> callback){ log("jsbcustom::JSBClass::jsbTestCallBack call,and call callback with \"parameter=73\" immediately!!!"); callback(73);}
上述c++类其实就是普通的符合cocos2d-x自动内存管理规范的c++类,由于只是测试,所以只是使用了最简单基本的实现。
2、定义手动绑定处理文件jsb_custom_auto.h和jsb_custom_auto.cpp
jsb_custom_auto.h声明对JSBClass进行js绑定的方法:
#pragma once#include "jsapi.h";#include "jsfriendapi.h"#include "ScriptingCore.h"// 自定义jsbcustom命名空间下的类或函数等的jsb注册入口void register_all_jsbcustom_jsb(JSContext* bindJSContext,JS::HandleObject bindObj);// 注册jsbcustom命名空间下的函数void jsb_register_jsbcustom_global(JSContext *bindJSContext, JS::HandleObject obj);bool jsb_jsbcustom_globalFunc_jsbTest(JSContext *bindJSContext, uint32_t argc, jsval *vp); // 具体绑定方法实现// 注册jsbcustom命名空间下的类void jsb_register_jsbcustom_JSBCLASS_class(JSContext *bindJSContext, JS::HandleObject obj); // 具体绑定类的绑定实现bool jsb_jsbcustom_JSBCLASS_constructor(JSContext *bindJSContext, uint32_t argc, jsval *vp); // 具体绑定类的构造方法绑定实现void jsb_jsbcustom_JSBCLASS_finalize(JSFreeOp *fop, JSObject *obj); // 具体绑定类的析构方法绑定实现bool jsb_jsbcustom_JSBCLASS_st_create(JSContext *bindJSContext, uint32_t argc, jsval *vp); // 具体绑定类的静态create方法绑定实现bool jsb_jsbcustom_JSBCLASS_jsbTestShow(JSContext *bindJSContext, uint32_t argc, jsval *vp); // 具体绑定类的具体方法绑定实现bool jsb_jsbcustom_JSBCLASS_jsbTestGetInt(JSContext *bindJSContext, uint32_t argc, jsval *vp); // 具体绑定类的具体方法绑定实现bool jsb_jsbcustom_JSBCLASS_jsbTestCallBack(JSContext *bindJSContext, uint32_t argc, jsval *vp); // 具体绑定类的具体方法绑定实现bool jsb_jsbcustom_JSBCLASS_jsbTest_callback(JSContext *bindJSContext, uint32_t argc, jsval *vp); // 具体绑定类的属性方法回调实现
其中jsb_custom_auto.cpp进行具体的绑定处理:
#include "jsb_custom_auto.h"#include "cocos2d.h"#include "JSBClass.h"#include "cocos2d_specifics.hpp"#include <string>void register_all_jsbcustom_jsb(JSContext* bindJSContext,JS::HandleObject bindObj){ JS::RootedObject newBindObj(bindJSContext); // 第一步:注册命名空间:jsbcustom,(后续二三可以不分先后) get_or_create_js_obj(bindJSContext, bindObj, "jsbcustom", &newBindObj); // 第二步:注册命名空间下的全局函数 jsb_register_jsbcustom_global(bindJSContext,newBindObj); // 第三步:注册命名空间下的类 jsb_register_jsbcustom_JSBCLASS_class(bindJSContext,newBindObj);}void jsb_register_jsbcustom_global(JSContext *bindJSContext, JS::HandleObject bindObj){ JS_DefineFunction(bindJSContext, bindObj, "st_jsbTest", jsb_jsbcustom_globalFunc_jsbTest, 0, 0);}bool jsb_jsbcustom_globalFunc_jsbTest(JSContext *bindJSContext, uint32_t argc, jsval *vp){ if (argc==0) { auto args = JS::CallArgsFromVp(argc, vp); jsbcustom::globalFunc_jsbTest(); args.rval().setUndefined(); return true; } JS_ReportError(bindJSContext, "jsb_jsbcustom_globalFunc_jsbTest: wrong number of arguments: %d, was expecting %d", argc, 0); return false;}void jsb_register_jsbcustom_JSBCLASS_class(JSContext *bindJSContext, JS::HandleObject obj){ // C++类要绑定到的js类句柄 JSClass *jsb_jsbcustom_jsbclass_class; jsb_jsbcustom_jsbclass_class = (JSClass *)calloc(1, sizeof(JSClass)); jsb_jsbcustom_jsbclass_class->name = "JSBCLASS"; // 新类绑定变化项:名字(JS中调用的对应类名) jsb_jsbcustom_jsbclass_class->addProperty = JS_PropertyStub; jsb_jsbcustom_jsbclass_class->delProperty = JS_DeletePropertyStub; jsb_jsbcustom_jsbclass_class->getProperty = JS_PropertyStub; jsb_jsbcustom_jsbclass_class->setProperty = JS_StrictPropertyStub; jsb_jsbcustom_jsbclass_class->enumerate = JS_EnumerateStub; jsb_jsbcustom_jsbclass_class->resolve = JS_ResolveStub; jsb_jsbcustom_jsbclass_class->convert = JS_ConvertStub; jsb_jsbcustom_jsbclass_class->finalize = jsb_jsbcustom_JSBCLASS_finalize; // 新类绑定变化项:析构处理 jsb_jsbcustom_jsbclass_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2); static JSPropertySpec properties[] = // 新类绑定变化项:成员变量 { JS_PS_END }; static JSFunctionSpec funcs[] = // 新类绑定变化项:成员函数 { JS_FN("jsbTestShow", jsb_jsbcustom_JSBCLASS_jsbTestShow, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("jsbTestGetInt", jsb_jsbcustom_JSBCLASS_jsbTestGetInt, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("jsbTestCallBack", jsb_jsbcustom_JSBCLASS_jsbTestCallBack, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("jsbTest_callback", jsb_jsbcustom_JSBCLASS_jsbTest_callback, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FS_END }; static JSPropertySpec st_properties[] = // 新类绑定变化项:静态变量 { JS_PS_END }; static JSFunctionSpec st_funcs[] = // 新类绑定变化项:静态函数 { JS_FN("create", jsb_jsbcustom_JSBCLASS_st_create, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FS_END }; // C++类要绑定到的js类原型句柄 JSObject *jsb_jsbcustom_jsbclass_prototype; jsb_jsbcustom_jsbclass_prototype = JS_InitClass( bindJSContext, obj, JS::NullPtr(), // 新类绑定变化项:基类句柄 jsb_jsbcustom_jsbclass_class, jsb_jsbcustom_JSBCLASS_constructor, 0, // 新类绑定变化项:构造函数及其参数个数 properties, funcs, st_properties, st_funcs); // 添加js类到js信息Hash表 TypeTest<jsbcustom::JSBClass> t; std::string typeName = t.s_name(); if (_js_global_type_map.find(typeName) == _js_global_type_map.end()) { js_type_class_t *p = (js_type_class_t *)malloc(sizeof(js_type_class_t)); p->jsclass = jsb_jsbcustom_jsbclass_class; p->proto = jsb_jsbcustom_jsbclass_prototype; p->parentProto = NULL; // 新类绑定变化项:基类原型句柄 _js_global_type_map.insert(std::make_pair(typeName, p)); }}bool jsb_jsbcustom_JSBCLASS_constructor(JSContext *bindJSContext, uint32_t argc, jsval *vp){ if (argc==0) { auto args = JS::CallArgsFromVp(argc, vp); auto jsret = JSVAL_NULL; auto ret = new jsbcustom::JSBClass(); if (ret) { ret->autorelease(); auto jsProxy = js_get_or_create_proxy<jsbcustom::JSBClass>(bindJSContext, (jsbcustom::JSBClass*)ret); jsret = OBJECT_TO_JSVAL(jsProxy->obj); } args.rval().set(jsret); return true; } JS_ReportError(bindJSContext, "jsb_jsbcustom_JSBCLASS_constructor: wrong number of arguments: %d, was expecting %d", argc, 0); return false;}void jsb_jsbcustom_JSBCLASS_finalize(JSFreeOp *fop, JSObject *obj){ log("jsbindings: finalizing JS object %p (JSBCLASS)", obj);}bool jsb_jsbcustom_JSBCLASS_st_create(JSContext *bindJSContext, uint32_t argc, jsval *vp){ if (argc == 0) { auto args = JS::CallArgsFromVp(argc, vp); auto jsret = JSVAL_NULL; auto ret = jsbcustom::JSBClass::create(); if (ret) { auto jsProxy = js_get_or_create_proxy<jsbcustom::JSBClass>(bindJSContext, (jsbcustom::JSBClass*)ret); jsret = OBJECT_TO_JSVAL(jsProxy->obj); } args.rval().set(jsret); return true; } JS_ReportError(bindJSContext, "jsb_jsbcustom_JSBCLASS_st_create : wrong number of arguments: %d, was expecting %d", argc, 0); return false;}bool jsb_jsbcustom_JSBCLASS_jsbTestShow(JSContext *bindJSContext, uint32_t argc, jsval *vp){ if (argc == 1) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); js_proxy_t *proxy = jsb_get_js_proxy(JS::RootedObject(bindJSContext, args.thisv().toObjectOrNull())); auto cobj = (jsbcustom::JSBClass*)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2(cobj, bindJSContext, false, "js_imcustom_class_jsbTest: Invalid Native Object"); JSString *jsstr = JS::ToString( bindJSContext, args.get(0)); JSStringWrapper jsstrw(jsstr); std::string arg0(jsstrw.get()); cobj->jsbTestShow(arg0); args.rval().setUndefined(); return true; } JS_ReportError(bindJSContext, "jsb_jsbcustom_JSBCLASS_jsbTestShow : wrong number of arguments: %d, was expecting %d", argc, 1); return false;}bool jsb_jsbcustom_JSBCLASS_jsbTestGetInt(JSContext *bindJSContext, uint32_t argc, jsval *vp){ if (argc == 0) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); js_proxy_t *proxy = jsb_get_js_proxy(JS::RootedObject(bindJSContext, args.thisv().toObjectOrNull())); auto cobj = (jsbcustom::JSBClass*)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, bindJSContext, false, "js_imcustom_class_jsbGetTest : Invalid Native Object"); int ret = cobj->jsbTestGetInt(); jsval jsret = JSVAL_NULL; jsret = INT_TO_JSVAL(ret); args.rval().set(jsret); return true; } JS_ReportError(bindJSContext, "jsb_jsbcustom_JSBCLASS_jsbTestGetInt : wrong number of arguments: %d, was expecting %d", argc, 0); return false;}bool jsb_jsbcustom_JSBCLASS_jsbTestCallBack(JSContext *bindJSContext, uint32_t argc, jsval *vp){ if (argc >= 1) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::RootedObject obj(bindJSContext, args.thisv().toObjectOrNull()); js_proxy_t *proxy = jsb_get_js_proxy(obj); auto cobj = (jsbcustom::JSBClass*)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, bindJSContext, false, "jsb_register_imcustom_jsbCallBack : Invalid Native Object"); std::function<void(int)> callback = [&](int state) { JS::Heap<JS::Value> js_TestCallback(JSVAL_VOID); js_TestCallback = args.get(0); JS::AddNamedValueRoot(bindJSContext, &js_TestCallback, "imcustom_jsbCallBack_func"); JS::Heap<JS::Value> js_TestCallbackThis(JSVAL_VOID); js_TestCallbackThis = argc==2?args.get(1):OBJECT_TO_JSVAL(obj); JS::AddNamedValueRoot(bindJSContext, &js_TestCallbackThis, "imcustom_jsbCallBack_this"); if(!js_TestCallback.isNullOrUndefined()) { jsval data = INT_TO_JSVAL(state); auto argsVal = JS::HandleValueArray::fromMarkedLocation(1, &data); JS::RootedValue retval(bindJSContext); JS_CallFunctionValue(bindJSContext, JS::RootedObject(bindJSContext, js_TestCallbackThis.toObjectOrNull()), JS::RootedValue(bindJSContext, js_TestCallback.get()), argsVal, &retval); } }; cobj->jsbTestCallBack(callback); args.rval().setUndefined(); return true; } JS_ReportError(bindJSContext, "jsb_jsbcustom_JSBCLASS_jsbTestCallBack : wrong number of arguments: %d, was expecting %d|%d", argc, 1,2); return false;}bool jsb_jsbcustom_JSBCLASS_jsbTest_callback(JSContext *bindJSContext, uint32_t argc, jsval *vp){ if (argc == 0) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); js_proxy_t *proxy = jsb_get_js_proxy(JS::RootedObject(bindJSContext, args.thisv().toObjectOrNull())); if (proxy) { jsval dataVal[2]; dataVal[0] = INT_TO_JSVAL(32); dataVal[1] = UINT_TO_JSVAL(88); ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(proxy->obj), "callback", 2, dataVal); } args.rval().setUndefined(); return true; } JS_ReportError(bindJSContext, "jsb_jsbcustom_JSBCLASS_jsbTest_callback : wrong number of arguments: %d, was expecting %d", argc, 0); return false;}
3、执行绑定初始化
AppDelegate::applicationDidFinishLaunching()方法中进行新绑定注册:
sc->addRegisterCallback(register_all_jsbcustom_jsb);
4、编译新类库后JS端测试运行
// jsbcustom命名空间下全局方法测试 jsbcustom.st_jsbTest(); // 构造函数绑定测试 var jsbcustomVal = new jsbcustom.JSBCLASS(); // create静态方法绑定测试 var s_jsbcustomVal = jsbcustom.JSBCLASS.create(); // jsbTestShow成员方法绑定测试 jsbcustomVal.jsbTestShow("call from js!!!"); // jsbTestGetInt成员方法绑定测试 var getjsbInt = jsbcustomVal.jsbTestGetInt(); cc.log("call from js,get a result = %s!!!",getjsbInt); // jsbTestCallBack成员方法绑定测试 jsbcustomVal.jsbTestCallBack(function(state) { cc.log("set a callback from js,get parameter state = %s!!!,state"); },this); // 回调成员变量句柄callback测试 jsbcustomVal.callback = function(state1,state2) { cc.log("set a \"jsbcustomVal.callback\"callback from js,get state1 = %s,state2=%s!!!",state1,state2); }; jsbcustomVal.jsbTest_callback();
结束
3 0
- Cocos2d-js JSB绑定学习笔记
- Cocos2d-JS自动JSB绑定规则修改
- Cocos2d-JS自动JSB绑定规则修改
- Cocos2d-JS自动JSB绑定规则修改
- Cocos2d-JS自动JSB绑定规则修改
- cocos2d-js 3.0 RC0 手动绑定 C++调用js,js调用C++ jsb
- Cocos2d-x JSB 自动绑定bindings
- Cocos2d-x JSB 自动绑定bindings
- JavaScript强化教程 —— Cocos2d-JS自动JSB绑定规则修改
- cocos2d js jsb XMLHttpRequest 中文乱码
- cocos2d js jsb XMLHttpRequest 中文乱码
- cocos2d-js开篇 - JSB环境打造
- Cocos2d-js学习笔记
- Cocos2d-js 3.0 jsb环境调用底层Objective-C代码
- cocos2d-js | JSB 调用Java函数 | Android设备ID
- JS学习笔记-事件绑定
- jsb 自动绑定
- jsb 自动绑定
- springboot多模块(modules)开发
- spark streaming 读取kafka数据问题
- CSS3D--立方体
- 算法导论最长公共子序列
- HTML5 from表单
- Cocos2d-js JSB绑定学习笔记
- Java内存溢出及解决办法
- spring+sparingmvc+codis
- CSS3D--翻转
- const
- 高斯模糊实现&RenderScript(渲染脚本)
- Android AnalogClock和DigitalClock类
- 欢迎使用CSDN-markdown编辑器
- FFMPEG 用H264编码封装mp4 有声音无图像。或者解码错误