Js C++手动绑定(案例1)
一,示例js绑定c++的过程,实现在js中设定应用程序的“设计分辨率”以及在c++中调用js脚本。
二,手动绑定入口
新建一个.h文件,此处定义为“JsbUtil.h”,定义函数:void register_jsb_util(JSContext *cx, JSObject *global);
参数含义简介:
cx:
几乎所有的js api都要求我们传递一个上下文做为参数。在cocos2d-x中的js上下文在类ScriptingCore中定义:rt_。它就像是一台小机器,它涉及JavaScript代码和对象的很 多东西。它可以编译和执行脚本、获取和设置对象属性、调用JavaScript函数、一种类型转换为另一种JavaScript数据、创建对象,等等。
global:
全局js对象,全局对象包含所有可以在JavaScript代码中使用 的类、函数和变量。
三,实现绑定入口函数
新建一个.cpp文件,此处命名为“JsbUtil.cpp”。
首先声明两个变量:
JsClass *js_util_class; //要和c++绑定的js类
JsObject *js_util_prototype; //在创建上述class类时的原型
第二步中声明函数的实现如下:
- /*
- 此函数做的事情:
- 1,为js_util_class分配空间
- 2,设置js_util_class的各个属性
- 3,设置要绑定的函数
- 4,获取js_util_class的原型
- 5,将js_util_class注册到全局属性中
- */
- void register_jsb_util(JSContext *cx, JSObject *global)
- {
- //js class的属性:https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/JSAPI_reference/JSClass
- js_util_class = (JSClass*)calloc(1, sizeof(JSClass));
- js_util_class->name = "APP_UTIL";//class 的name属性,这样可以在js脚本中直接new APP_UTIL()来使用此类
- js_util_class->addProperty = JS_PropertyStub;//在添加新属性后被调用的函数。默认使用“JS_PropertyStub”
- js_util_class->delProperty = JS_PropertyStub; //删除属性时被调用的函数。默认使用“JS_PropertyStub”
- js_util_class->getProperty = JS_PropertyStub; //获取一个属性时调用的函数。这是js类的默认获取属性的方法。默认使用“JS_PropertyStub”。
- js_util_class->setProperty = JS_StrictPropertyStub; //在一个脚本中新建一个属性后它会在调用“addProperty”之后被调用。默认使用“JS_StrictPropertyStub”。
- js_util_class->enumerate = JS_EnumerateStub; //枚举(enumrate)对象属性的方法。默认使用“JS_EnumerateStub”。
- js_util_class->resolve = JS_ResolveStub; //分解类中属性的函数
- js_util_class->convert = JS_ConvertStub; //对类中属性值进行转换的函数
- js_util_class->finalize = js_utility_finalize; //类的对象释放时调用的析构函数,<span style="font-family: Arial, Helvetica, sans-serif;">需要声明到此函数的前面,下一步实现</span>
- //类的属性(成员变量)。0表明属性不是一 个集合.JS_HAS_PRIVATE: 类可以使用私有数据.JS_NEW_ENUMERATE: 返回由类定义的getObjectOps方法获取所有属性的一个新方法.JS_NEW_RESOLVE: 返回由类定义的 getObjectOps方法获取属性值的一个新方法
- js_util_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2);
- //以上部分创建了一个js类,定义其属性:name,addProperty,delProperty, getProperty, setProperty, enumerate, resolve, convert, finalize, flags.
- //要注册的属性
- //struct JSPropertySpec {
- // const char *name; //Name to assign the property
- // int8 tinyid; //Obsolete since JSAPI 31 Unique ID number for the property to aid in resolving getProperty and setProperty method calls.
- //This value should be zero if you are not using tinyIDs (i.e. the getter/setter function is only used by one property).
- // uint8 flags; //Property attributes.
- // JSPropertyOp getter; //Getter method for the property.
- // JSPropertyOp setter; //Setter method for the property. If a property is read-only, it's setter is never called.
- //};
- static JSPropertySpec properties[] = {
- {0, 0, 0, 0, 0}
- };
- //实例函数
- //struct JSFunctionSpec {
- // const char *name; //在js脚本中调用的函数名字;
- // JSNative call; //映射的本地函数名称
- // uint16 nargs; //The value used for Function.length. This no longer guarantees anything about the vp array.
- // uint16 flags; //The bitwise OR of any number of property attributes and function flags, and optionally JSFUN_STUB_GSOPS.
- // uint32 extra; //JSAPI 1.8 and earlier The lower 16 bits indicate the number of extra local roots the function desires,
- //available at argv[MAX(nargs, argc)] onward. The upper 16 bits must be zero and are currently reserved.
- //In older versions of SpiderMonkey, this field was a uint16 required to be 0.
- //};
- //#define JS_FN(name,call,nargs,flags) \
- //{name, JSOP_WRAPPER(call), nargs, (flags) | JSFUN_STUB_GSOPS}
- //#define JS_FS_END JS_FS(NULL,NULL,0,0)
- static JSFunctionSpec funcs[] = {
- JS_FN("setDesignResolution", js_util_set_design_resolution, 3, JSPROP_ENUMERATE|JSPROP_PERMANENT),
- JS_FS_END
- };
- //类函数:看cocos2dx中的绑定此处绑定的是类的静态函数
- // static JSFunctionSpec st_funcs[] = {
- // JS_FN("create", js_cocos2dx_CCNode_create, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE),
- // JS_FS_END
- // };
- static JSFunctionSpec st_funcs[] = {
- JS_FS_END
- };
- //初始化js类
- //JS_InitClass : Make a JSClass accessible to JavaScript code by creating its prototype, constructor, properties, and functions.
- // JSObject * JS_InitClass(JSContext *cx, //Pointer to a JS context from which to derive runtime information. Requires request.
- //In a JS_THREADSAFE build, the caller must be in a request on this JSContext.
- // JSObject *obj, //Pointer to the "globals" object to use for initializing the class.
- // JSObject *parent_proto,// Pointer to an object to be used as a prototype
- // JSClass *clasp, //Pointer to the class structure to initialize. This structure defines the class for use by other API functions.
- // JSNative constructor,//The constructor for the class. Its scope matches that of the obj argument.
- //If constructor is NULL, then static_ps and static_fs must also be NULL.
- // uintN nargs, //Number of arguments for the constructor.
- // JSPropertySpec *ps, //Either NULL or a pointer to the first element of an array of JSPropertySpecs,
- //terminated by the null JSPropertySpec, which can be written {0, 0, 0, 0, 0}. 要注册的属性
- // JSFunctionSpec *fs, //Either NULL or a pointer to the first element of an array of JSFunctionSpecs, terminated by JS_FS_END.
- // 要注册的函数
- // JSPropertySpec *static_ps, //Either NULL or a pointer to the first element of an array of JSPropertySpecs, terminated by the null JSPropertySpec.
- // JSFunctionSpec *static_fs);
- js_util_prototype = JS_InitClass(cx,
- global,
- NULL,
- js_util_class,
- js_util_constructor,//需要声明到此函数的前面,下一步实现
- 0,
- properties,
- funcs,
- NULL,
- st_funcs);
- //注册到全局变量中
- JSBool found;
- JS_SetPropertyAttributes(cx, global, "APP_UTIL", JSPROP_ENUMERATE|JSPROP_READONLY, &found);
- }
四,定义js类的析构和构造函数
析够函数定义如下:
- void js_utility_finalize(JSFreeOp *op, JSObject *obj)
- {
- CCLOG("js_util_class is free : %p", obj);
- }
构造函数定义如下:
- JSBool js_util_constructor(JSContext *cx, uint32_t argc, jsval *vp)
- {
- if (argc != 0) {
- JS_ReportError(cx, "Wrong number of args: %d, was expecting: %d", argc, 0);
- return JS_FALSE;
- }
- JSObject *obj = JS_NewObject(cx, js_util_class, js_util_prototype, NULL);
- UtilHelper *cobj = new UtilHelper();//绑定的本地c++类,下一步实现
- //Link the native object with the javascript object
- js_proxy_t *p = jsb_new_proxy(cobj, obj);
- JS_AddNamedObjectRoot(cx, &p->obj, "APP_UTIL");
- //设置js构造函数的返回值为obj
- JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
- return JS_TRUE;
- }
五,本地c++相关代码(UtilHelper)的实现
在此简略实现,直接定义在“JsbUtil.cpp”文件中,现在只实现一个功能:设置项目的分辨率解决方案,如下:
- class UtilHelper
- {
- public:
- void setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy)
- {
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(width, height, resolutionPolicy);
- }
- };
六,实现绑定函数js_util_set_design_resolution
- /*
- 绑定设置designResolution的函数
- 根据当前的js object获取到其绑定的c++对象,再通过c++对象调用c++对象中的方法
- */
- JSBool js_util_set_design_resolution(JSContext *cx, uint32_t argc, jsval *vp)
- {
- if (argc != 3) {
- JS_ReportError(cx, "Wrong number of argc:%d, was expecting: %d", argc, 3);
- return JS_FALSE;
- }
- JSObject *obj_this = JS_THIS_OBJECT(cx, vp);
- js_proxy_t *proxy = jsb_get_js_proxy(obj_this);
- UtilHelper *cobj = (UtilHelper*)(proxy?proxy->ptr:NULL);
- JSB_PRECONDITION2(cobj, cx, JS_FALSE, "Invalid Native object");
- jsval *argv = JS_ARGV(cx, vp);
- int width = 0;
- if (JSVAL_IS_INT(argv[0])) {
- jsval_to_int32(cx, argv[0], &width);
- }
- int height = 0;
- if (JSVAL_IS_INT(argv[1])) {
- jsval_to_int32(cx, argv[1], &height);
- }
- std::string data;
- if(JSVAL_IS_STRING(argv[2])){
- jsval_to_std_string(cx, argv[2], &data);
- }
- ResolutionPolicy policy = kResolutionUnKnown;
- if (data == std::string("kResolutionExactFit")) {
- policy = kResolutionExactFit;
- }else if(data == std::string("kResolutionNoBorder")){
- policy = kResolutionNoBorder;
- }else if(data == std::string("kResolutionFixedHeight")){
- policy = kResolutionFixedHeight;
- }else if(data == std::string("kResolutionFixedWidth")){
- policy = kResolutionFixedWidth;
- }else if(data == std::string("kResolutionShowAll")){
- policy = kResolutionShowAll;
- }
- cobj->setDesignResolutionSize(width, height, policy);
- return JS_TRUE;
- }
新建test_util.js文件放在Resource/script目录下,添加如下代码:
- require("jsb.js")
- var director = cc.Director.getInstance();
- var winSize = director.getWinSize();
- var scene = cc.Scene.create();
- var testSprite = cc.Sprite.create('HelloWorld.png'); //使用系统自带的图片,分辨率为480x320
- scene.addChild(testSprite);
- testSprite.setPosition(cc.p(winSize.width/2, winSize.height/2));
- director.runWithScene(scene);
1,添加绑定:sc->addRegisterCallback(register_jsb_util);
2,修改执行的脚本为test_util.js:ScriptingCore::getInstance()->runScript("script/test_util.js");
之后使用480x320的模拟器效果图如下:
切换到分辨率大的模拟器后不能再全屏:
在require("jsb.js")下添加如下代码:
- var util = new APP_UTIL();
- util.setDesignResolution(480, 320, 'kResolutionFixedHeight');
之后运行效果如下:
九,添加c++回调脚本的功能
在UtilHelper中添加如下代码:
- void CallBackJs()
- {
- JSContext *cx = ScriptingCore::getInstance()->getGlobalContext();
- JSObject *jsobj = JS_NewObject(cx, NULL, NULL, NULL);
- // 组织传递给脚本的参数
- int attr1Val = 1;
- jsval vp;
- vp = int32_to_jsval(cx, attr1Val);
- JS_SetProperty(cx, jsobj, "myAttr1", &vp);
- jsval args = OBJECT_TO_JSVAL(jsobj);
- //转给脚本
- ScriptingCore::getInstance()->executeFunctionWithOwner(OBJECT_TO_JSVAL(m_pJsDelegate), "onTestCallJs", 1, &args);
- }
- void SetJsDelegate(JSObject *pDelegate) {
- m_pJsDelegate = pDelegate;
- }
- private:
- JSObject *m_pJsDelegate;
- void setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy)
- {
- CCEGLView::sharedOpenGLView()->setDesignResolutionSize(width, height, resolutionPolicy);
- CallBackJs();
- }
- JSBool js_util_constructor(JSContext *cx, uint32_t argc, jsval *vp)
- {
- if (argc != 0) {
- JS_ReportError(cx, "Wrong number of args: %d, was expecting: %d", argc, 0);
- return JS_FALSE;
- }
- JSObject *obj = JS_NewObject(cx, js_util_class, js_util_prototype, NULL);
- UtilHelper *cobj = new UtilHelper();
- cobj->SetJsDelegate(obj); //添加此句
- .....
- }
在test_util.js脚本中实现onTestCallJs:
- var util = new APP_UTIL();
- util.onTestCallJs = function(arg) {
- cc.log('call by c++, arg is = ' + JSON.stringify(arg));//打印出c++传递来的参数
- };
十,至此,js\C++手动绑定,混合调用示例书写完毕。
相关参考:
JavaScript-C/C++ (SpiderMonkey) 引擎嵌入开发指南(中文向导)
JSAPI_reference相关推荐
- Js C++手动绑定(案例1)
- 【cocos2d-x从c++到js】12:回调函数1——按键回调
- ACR1251U-M1蓝牙NFC读卡器软件开发包包含Java/.NET/C++/Delphi代码案例
- React.js hooks 练习案例-网易云音乐【day1】
- Jquery 模板插件 jquery.tmpl.js 的使用方法(1):基本语法,绑定,each循环,ajax获取json数据...
- vue.js基础知识篇(1):简介、数据绑定
- JavaWeb_BootStrap每日学习Day1---Bootstrap简介、Bootstrap栅格系统、Bootstrap中的CSS样式和组件和JS插件、案例
- 绑定(...)总是返回-1使用WinSock2 - C++
- 【cocos2d-x从c++到js】12:回调函数1——按键回调
- 【cocos2d-x从c++到js】09:JS与C++的交互1——JS代码调用C++代码
- Spark性能优化:提高并行度、使用reduceByKey
- [转载]ppt文件怎么打开就自动放映呢?