`
eric_weitm
  • 浏览: 235056 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

集成spiderMonkey

阅读更多
集成spiderMonkey
文档 :https://developer.mozilla.org/En/SpiderMonkey/JSAPI_User_Guide
https://developer.mozilla.org/en/How_to_embed_the_JavaScript_engine

一、hello world基本流程:
    JS_NewRuntime
    JS_NewContext
    JS_SetOptions
    JS_SetErrorReporter
    JS_NewCompartmentAndGlobalObject ------创建global对象
    JS_InitStandardClasses ---------------- 把运行时内置的函数、对象、常量等作为global object的属性导出
    ok = JS_EvaluateScript(cx, global, script, strlen(script), filename, lineno, &rval); ----解释执行

    if (rval == NULL | rval == JS_FALSE) // 判断运行状态
        return 1;

    str = JS_ValueToString(cx, rval);    // 处理运行结果

二、暴漏c的函数(本地的wrapper是作为js的回调挂上去的)
    本地wrapper的基本格式要求 typedef JSBool (*JSNative)(JSContext *cx, uintN argc, jsval *vp);
    1、返回值是 JSBool(JS_TRUE 正常得到结果,JS_FALSE执行时出现异常)
    2、第一个参数是 JSContext
    3、第二个参数是 argc(js代码中传进来的参数个数)
    4、第三个参数是 jsval *, 可以用来取得参数、this、返回值等
    5、调用成功时 JS_SET_RVAL + return JS_TRUE
       调用失败时 JS_ReportError + return JS_FALSE

三、常用技术
    1、JS_ARGV(cx, vp)  指向参数数组的第一个元素
    2、JS_RVAL(cx, vp)  指向返回值
    3、JS_SET_RVAL(cx, vp, value) 设置返回值
    4、JS_THIS_OBJECT(cx, vp) 取this对象
    5、JS_THIS(cx, vp)    jsVal版本的this
    6、JS_CALLEE(cx, vp)  被调用的函数对象

四、例子
JSBool myjs_rand(JSContext *cx, uintN argc, jsval *vp)
{
    JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL(rand()));
    return JS_TRUE;
}

/* A wrapper for the srand() function, from the C standard library.
   This example shows how to handle optional arguments. */
JSBool myjs_srand(JSContext *cx, uintN argc, jsval *vp)
{
    uint32 seed;
     // 把输入的参数转变格式,存入输出中, 参数依次是cx,调用者传入参数个数,传入的参数,输出的格式,输出地址
    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/u", &seed))
        return JS_FALSE;

    /* If called with no arguments, use the current time as the seed. */
    if (argc == 0)
        seed = time(NULL);

    srand(seed);// 初始化一个种子

    JS_SET_RVAL(cx, vp, JSVAL_VOID);  /* return undefined */
    return JS_TRUE;
}

/* A wrapper for the system() function, from the C standard library.
   This example shows how to report errors. */
JSBool myjs_system(JSContext *cx, uintN argc, jsval *vp)
{
    JSString* str;
    char *cmd;
    int rc;

    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "s", &str))
        return JS_FALSE;

    cmd = JS_EncodeString(cx, str); // js string 转成 c的char *
    rc = system(cmd);
    JS_free(cx, cmd);// 不用了,释放掉
    if (rc != 0) {
        /* Throw a JavaScript exception. */
        JS_ReportError(cx, "Command failed with exit code %d", rc);// 抛出异常给js,js中可以用try catch检测到
        return JS_FALSE;
    }

    JS_SET_RVAL(cx, vp, JSVAL_VOID);  /* return undefined 没有返回值时也要显示的设置一下*/
    return JS_TRUE;
}

      //加入自定义函数
     JSFunctionSpec my_functions[] = {
         JS_FS("myprint", myprint, 0, 0, 0), // 依次是name, notive func, argc, tags, extra
         JS_FS_END
     };

     JS_DefineFunctions(cx, objParent, my_functions);

五、暴漏对象 JS_InitClass + JS_DefineProperties

顺序:
    1、属性id枚举
    2、getter, constructer, destructer
    3、class的template
    4、class的函数表
    5、JS_InitClass
    6、JS_DefineProperties

网上找的一个例子:

***************************************************************************** getter, constructer, destructer******
       // 属性Getter函数
       enum{ EQFRONT, EQBACK, EQSIZE, EQEMPTY, EQARRAY};
       JSBool MyClassGetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
       {
           std::deque<int>* pQ = (std::deque<int>*)JS_GetPrivate(cx, obj);
           if(!JSVAL_IS_INT(id)) return JS_TRUE;
           switch(JSVAL_TO_INT(id))
           {
           case EQFRONT:
            if(pQ->empty()) return JS_FALSE;
            *vp = INT_TO_JSVAL( pQ->front() );
            break;

        case EQBACK:
            if(pQ->empty()) return JS_FALSE;
            *vp = INT_TO_JSVAL( pQ->back() );
            break;

        case EQSIZE:
            *vp = INT_TO_JSVAL( pQ->size() );
            break;

        case EQEMPTY:
            *vp = BOOLEAN_TO_JSVAL( pQ->empty() );
            break;

        case EQARRAY: //数组操作
            {
                //用JS_NewArrayObject生成数组
                JSObject *objA = JS_NewArrayObject(cx, 0, NULL);
                jsint idx = 0;

                for(std::deque<int>::iterator itr=pQ->begin(); itr!=pQ->end(); ++itr)
                {
                    jsval v = INT_TO_JSVAL(*itr);
                    //用JS_SetElement加入指定索引的数据
                    JS_SetElement(cx, objA, idx++, &v);
                }
                *vp = OBJECT_TO_JSVAL(objA);
                break;
            }
            break;
        }
        return JS_TRUE;
    }

    // "构造"
    JSBool MyClassConstructor(JSContext *cx, JSObject *obj, uintN argc,
        jsval *argv, jsval *rval)
    {
        std::deque<int> *pQ = new std::deque<int>();
        JS_SetPrivate(cx, obj, pQ);
        return JS_TRUE;
    }

    // "析造"
    void MyClassDestructor(JSContext *cx, JSObject *obj)
    {
        std::deque<int>* pQ = (std::deque<int>*)JS_GetPrivate(cx, obj);
        delete pQ;
    }

******************************************class template*****************************************
    // 定义类
JSClass myClass={
   "MyClass",                         // name
   JSCLASS_HAS_PRIVATE,               // tags
   JS_PropertyStub, JS_PropertyStub,  // 添加、删除属性的回调 默认是 JS_PropertyStub
   MyClassGetter, JS_PropertyStub,    // get set方法
   JS_EnumerateStub,                  // 遍历属性
   JS_ResolveStub,                    // 解析不存在的属性
   JS_ConvertStub,                    // 转成原子类型
   MyClassDestructor                  // 析构函数
};

*******************************************class的函数表***************************************
    // 类方法
    JSBool QPush(JSContext *cx, JSObject *obj, uintN argc,
            jsval *argv, jsval *rval)
    {
        std::deque<int>* pQ = (std::deque<int>*)JS_GetPrivate(cx, obj);
        if(JSVAL_IS_INT(argv[0]))
        {
            pQ->push_back(JSVAL_TO_INT(argv[0]));
        }
        return JS_TRUE;
    }

    JSBool QPop(JSContext *cx, JSObject *obj, uintN argc,
            jsval *argv, jsval *rval)
    {
        std::deque<int>* pQ = (std::deque<int>*)JS_GetPrivate(cx, obj);
        if(!pQ->empty())
        {
            pQ->pop_front();
        }
        return JS_TRUE;
    }

   JSFunctionSpec myClassMethod[]={
       JS_FS("push", QPush, 1, 0, 0),   // 依次是name, notive func, argc, tags, extra
       JS_FS("pop", QPop, 0, 0, 0),
       JS_FS_END
   };

*****************************************JS_InitClass****************************
    JSObject * newobj = JS_InitClass(cx, objParent, NULL, // cx, global obj, prototype,
        &myClass, MyClassConstructor, 0,                  // 类构成模板,构造函数,构造函数参数个数
        NULL, myClassMethod,                              // prototype中的属性和方法
        NULL, NULL);                                      // 构造函数的属性和方法

**************************************JS_DefineProperties************************
    JSPropertySpec myClassProp[]={
        {"front", EQFRONT, JSPROP_READONLY}, // names, c实现中的唯一id, flags,  get函数, set函数
        {"back", EQBACK, JSPROP_READONLY},
        {"size", EQSIZE, JSPROP_READONLY},
        {"empty", EQEMPTY, JSPROP_READONLY},
        {"array", EQARRAY, JSPROP_READONLY},
        {0}
    };

    JS_DefineProperties(cx, newobj, myClassProp);
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics