VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 11557|回复: 1

[分享] SpiderMonkey_31.2.0版编程笔记 六___对象操作二

[复制链接]
04_avatar_middle
online_vip 发表于 2015-9-16 15:56:25 | 显示全部楼层 |阅读模式
本帖最后由 liehuo 于 2015-9-17 08:41 编辑

这次我将对一个对象添加成员方法,同时一次性多添加几个属性。一次性添加多个属性说白了也没什么,不过调用一个函数而已。这个函数名字叫JS_DefineProperties,原型如下:
bool JS_DefineProperties(JSContext *cx, JS::HandleObject obj, const JSPropertySpec *ps);
参数cx不用说都知道,obj就是你要为哪个对象添加属性,ps是重要的东西,全靠它我们才能一次添加多个属性。JSPropertySpec 不过是一个结构体而已,定义一个JSPropertySpec 类型的结构体变量,然后依次填充内部成员,最后把结构体地址传入JS_DefineProperties函数里就行了,多个属性就定义多个JSPropertySpec 类型变量,干脆我们就定义一个JSPropertySpec 类型数组,把数组首地址传入就完事了。不过我们不用那么费劲一个个填充成员,人家也提供了一个宏JS_PSGS,跟定义多个函数一样都有对应的宏,使用方法大同小易,也要全0结尾的一个结构,也有对应的宏叫JS_PS_END。还是看看什么样子吧:
static const JSPropertySpec my_props[] = {
        JS_PSGS("age", AgeGetPro, AgeSetPro, JSPROP_ENUMERATE),
        JS_PSGS("name", NameGetPro, NameSetPro, JSPROP_ENUMERATE),
        JS_PS_END
};
其中AgeGetPro和AgeSetProAgeSetPro是回调函数,回调函数有固定的写法,实现bool(* JSNative)(JSContext *cx, unsigned argc, JS::Value *vp)样式,名字随便起。
  1. static bool AgeSetPro(JSContext *cx, unsigned argc, JS::Value *vp)
  2. {
  3.         CallArgs args = CallArgsFromVp(argc, vp);
  4.         age = args[0].toInt32();
  5.         HandleValue thisValue = args.thisv();
  6.         JSObject *pThis = &thisValue.toObject();
  7.         JS_SetPrivate(pThis, &age);
  8.         return true;
  9. }
复制代码
给对象添加成员函数就更简单了,在讲述函数的帖子时候都已经提到使用方法了,不过就是把全局对象换成自定义对象,其它不变就行了。一看代码就知道怎么回事了:
  1. #include "stdafx.h"
  2. #include "include/jsapi.h"
  3. #pragma comment(lib,"lib/mozjs-31.lib")//这里直接用这种方式,是为了观看方便
  4. using namespace JS;
  5. int age = 0;                             //目的用来保存AgeSetPro回调里的age参数,在AgeGetPro的回调函数里再设置返回去
  6. char *name = nullptr;                    //目的用来保存NameSetPro回调里的name参数,在NameGetPro的回调函数里再设置返回去
  7. static JSClass global_class = {
  8.         "global",
  9.         JSCLASS_GLOBAL_FLAGS,
  10.         JS_PropertyStub,          //增加属性
  11.         JS_DeletePropertyStub,    //删除属性
  12.         JS_PropertyStub,          //获取属性
  13.         JS_StrictPropertyStub,    //设置属性
  14.         JS_EnumerateStub,
  15.         JS_ResolveStub,
  16.         JS_ConvertStub
  17. };
  18. JSClass my_class = {
  19.         "MyClass",
  20.         JSCLASS_HAS_PRIVATE,
  21.         JS_PropertyStub,
  22.         JS_DeletePropertyStub,
  23.         JS_PropertyStub,//用nullptr可以,//这样也可以(JSPropertyOp)AgeGetPro,
  24.         JS_StrictPropertyStub,//nullptr,//(JSStrictPropertyOp)AgeSetPro,
  25.         JS_EnumerateStub,
  26.         JS_ResolveStub,
  27.         JS_ConvertStub
  28. };
  29. static bool AgeGetPro(JSContext *cx, unsigned argc, JS::Value *vp)
  30. {
  31.         JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
  32.         int n2 = args[0].toInt32();
  33.         HandleValue thisValue = args.thisv();
  34.         JSObject *pThis = &thisValue.toObject();
  35.         int *p = (int*)JS_GetPrivate(pThis);
  36.         args.rval().setInt32(*p);
  37.         //*vp = INT_TO_JSVAL(age);//或者这样也可以,
  38.         return true;
  39. }
  40. static bool AgeSetPro(JSContext *cx, unsigned argc, JS::Value *vp)
  41. {
  42.         CallArgs args = CallArgsFromVp(argc, vp);
  43.         age = args[0].toInt32();
  44.         HandleValue thisValue = args.thisv();
  45.         JSObject *pThis = &thisValue.toObject();
  46.         JS_SetPrivate(pThis, &age);
  47.         return true;
  48. }
  49. static bool NameGetPro(JSContext *cx, unsigned argc, JS::Value *vp)
  50. {
  51.         JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
  52.         JSString *str = JS_NewStringCopyN(cx, name, strlen(name));
  53.         args.rval().setString(str);
  54.         return true;
  55. }
  56. static bool NameSetPro(JSContext *cx, unsigned argc, JS::Value *vp)
  57. {
  58.         CallArgs args = CallArgsFromVp(argc, vp);
  59.         JSString *str = args[0].toString();
  60.         name = JS_EncodeString(cx, str);
  61.         return true;
  62. }
  63. static bool JS_fun1(JSContext *cx, unsigned argc, jsval *vp)
  64. {
  65.         printf("fun1\n");
  66.         return true;
  67. }
  68. static bool JS_fun2(JSContext *cx, unsigned argc, jsval *vp)
  69. {
  70.         printf("fun2\n");
  71.         return true;
  72. }
  73. static const JSPropertySpec my_props[] = {
  74.         JS_PSGS("age", AgeGetPro, AgeSetPro, JSPROP_ENUMERATE),
  75.         JS_PSGS("name", NameGetPro, NameSetPro, JSPROP_ENUMERATE),
  76.         JS_PS_END
  77. };
  78. static const JSFunctionSpec my_methods[] = {
  79.         JS_FS("fun1", JS_fun1, 0, 0),
  80.         JS_FS("fun2", JS_fun2, 0, 0),
  81.         JS_FS_END
  82. };
  83. void ExecScript(JSContext *cx)
  84. {
  85.         JSObject *obj = JS_NewGlobalObject(cx, &global_class, nullptr, FireOnNewGlobalHook);//创建一个新的JS对象,用作一个全局对象,但是要被根化,这里没有被根化。
  86.         RootedObject global(cx, obj);//在当前的上下文环境,用创建的全局对象创建根化的全局对象
  87.         JSAutoCompartment ac(cx, global);//进入新全局对象的隔室,好像干什么坏事总是见不得人,非要躲在包厢里做坏事一样
  88.         JS_InitStandardClasses(cx, global);//初始化全局对象和其它js里的常规对象

  89.         JSObject *myObj = JS_DefineObject(cx, global, "myObject", &my_class, nullptr, JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SETTER);
  90.         RootedObject rotMyobj(cx, myObj);
  91.         JS_DefineProperties(cx, rotMyobj, my_props);
  92.         JS_DefineFunctions(cx, rotMyobj, my_methods);
  93.         const char *script = "var student=myObject;student.name='zhoujielun';student.age=30;\
  94.                                                  var name=student.name;var age=student.age;student.fun1();student.fun2();";
  95.         const char *filename = "noname";
  96.         int lineno = 1;

  97.         bool ok = JS_EvaluateScript(cx, global, script, strlen(script), filename, lineno);
  98.         RootedValue rval(cx);
  99.         JS_GetProperty(cx, global, "student", &rval);
  100.         if (rval.isObject())
  101.         {
  102.                 RootedObject stuobj(cx, JSVAL_TO_OBJECT(rval));
  103.                 RootedValue rval2(cx);
  104.                 JS_GetProperty(cx, global, "name", &rval2);
  105.                 JSString *s = rval2.toString();
  106.                 printf("name=%s\n", JS_EncodeString(cx, s));
  107.                 JS_GetProperty(cx, global, "age", &rval2);
  108.                 int js_age = rval2.toInt32();
  109.                 printf("age=%d\n", js_age);
  110.         }
  111.         printf("\n");
  112. }
  113. int _tmain(int argc, _TCHAR* argv[])
  114. {
  115.         JS_Init();     //初始化JS引擎,一定要有这步,不然其它的操作都是扯淡
  116.         JSRuntime *rt = JS_NewRuntime(8L * 1024 * 1024, JS_USE_HELPER_THREADS);//创建运行时,是不是跟以前的不一样了
  117.         if (!rt)
  118.                 return 1;
  119.         JSContext *cx = JS_NewContext(rt, 8192);//创建一个JS上下文,与运行时关联起来
  120.         if (!cx)
  121.                 return 1;
  122.         //****************************************************************************************
  123.             ExecScript(cx);
  124.         //****************************************************************************************
  125.         JS_DestroyContext(cx);//销毁创建的上下文
  126.         JS_DestroyRuntime(rt);//销毁释放运行时
  127.         JS_ShutDown();        //释放js引擎使用的所有资源
  128.         return 0;
  129. }
复制代码
运行结果: SpiderMonkey_31.2.0版编程笔记 六___对象操作二


不过虽然说能够得到正确答案,但是我始终觉得哪里不对劲,get属性方法和set属性方法里我用的是一个全局变量来保存的,就拿age来说,如果不用全局变量set时是age=30,但get时得到的就不是30了,怎么回事我也没有搞清楚,没办法用个全局变量来保存结果,然后再get的时候给返回出去。所以到了NameGetPro和NameSetPro时候根本就把JS_GetPrivate和JS_SetPrivate省略掉了,没必要了,直接把name返回出去args.rval().setString(str)就行了。这一点我请求哪位高手解惑迷津,感激不尽!
上一篇:SpiderMonkey_31.2.0版编程笔记 五___对象操作一
上一篇:SpiderMonkey_31.2.0版编程笔记 七___类操作




上一篇:SpiderMonkey_31.2.0版编程笔记 五___对象操作一
下一篇:SpiderMonkey_31.2.0版编程笔记 七__类操作
14_avatar_middle
在线会员 发表于 2015-11-17 16:18:50 | 显示全部楼层
感谢楼主的无私奉献
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-6-19 20:03

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表