真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

在C++中怎么執(zhí)行JavaScript程序-創(chuàng)新互聯(lián)

本篇內容介紹了“在C++中怎么執(zhí)行JavaScript程序”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

創(chuàng)新互聯(lián)建站網(wǎng)站建設服務商,為中小企業(yè)提供成都網(wǎng)站設計、做網(wǎng)站服務,網(wǎng)站設計,網(wǎng)站托管維護等一站式綜合服務型公司,專業(yè)打造企業(yè)形象網(wǎng)站,讓您在眾多競爭對手中脫穎而出創(chuàng)新互聯(lián)建站。

SpiderMonkey

SpiderMonkey是Mozilla項目的一部分,用C語言寫成,是負責執(zhí)行JavaScript腳本的引擎。另外還有一個叫Rhino的Java引擎。

SpiderMonkey的新版本可在這里下載。它是以源代碼形式發(fā)布的,因此你必須自己編譯它。Visual C++用戶可以在src目錄下找到Workspace項目工程文件來編譯,編譯結果會產(chǎn)生一個叫'js32.dll'的dll文件。

SpiderMonkey也可以在Macintosh和Unix上使用。

在C++中執(zhí)行JavaScript程序

步驟1-創(chuàng)建JavaScript runtime(運行時實例)

初始化一個JavaScript runtime可用JS_NewRuntime方法,該方法將為runtime分配內存,同時還得指定一個字節(jié)數(shù),當內存分配超過這個數(shù)字時垃圾收集器會自動運行。

JSRuntime *rt = JS_NewRuntime(1000000L);
if ( rt == NULL )
{
    // Do some error reporting
}


步驟2-創(chuàng)建context(上下文環(huán)境)

Context指明了腳本運行所需的棧大小,即分配給腳本執(zhí)行棧的私有內存數(shù)量。每個腳本都和它自己的context相關聯(lián)。

當一個context正在被某個腳本或線程使用時,其他腳本或線程不能使用該context。不過在腳本或線程結束時,該context可以被下一個腳本或線程重用。

創(chuàng)建一個新context可用JS_NewContext方法。context必須關聯(lián)到一個runtime,調用JS_NewContext方法時還必須指定棧的大小。

JSContext *cx = JS_NewContext(m_rt, 8192);
if ( cx == NULL )
{
    // Do some error reporting
}

步驟3-初始化全局對象

在一個腳本開始運行前,必須初始化一些大多數(shù)腳本會用到的通用的JavaScript函數(shù)和內置(build-in)類對象。

全局對象是在一個JSClass結構中描述的。該結構可以按以下方式初始化:

JSClass globalClass =
{
    "Global", 0,
    JS_PropertyStub,  JS_PropertyStub,
    JS_PropertyStub, JS_PropertyStub,
    JS_EnumerateStub, JS_ResolveStub,
    JS_ConvertStub,  JS_FinalizeStub
};

現(xiàn)在創(chuàng)建和初始化這個全局對象:JSObject *globalObj = JS_NewObject(cx, &globalClass, 0, 0);
JS_InitStandardClasses(cx, globalObj);

步驟4-執(zhí)行腳本

執(zhí)行腳本的一種途徑是使用JS_EvaluateScript方法:

std::string script = "var today = Date(); today.toString();"
jsval rval;
uintN lineno = 0;
JSBool ok = JS_EvaluateScript(cx, globalObj, script.c_str(), 
                              script.length(), "script", lineno, &rval);

在這個腳本中,如果運行正確的話當天數(shù)據(jù)會保存在rval中。rval包含最后一個執(zhí)行函數(shù)的結果。JS_EvaluteScript返回JS_TRUE代表執(zhí)行成功,返回JS_FALSE則代表有錯誤發(fā)生。

從rval得到相應的字符串值可以用下面的方法。在這里我不想解釋所有細節(jié),想獲得更詳細的信息請自己查API文檔。

JSString *str = JS_ValueToString(cx, rval);
std::cout << JS_GetStringBytes(str);

步驟5-清理腳本引擎

程序結束前必須對腳本引擎做一些清理工作:JS_DestroyContext(cx);
JS_DestroyRuntime(rt);

在C++中定義一個在JavaScript中用的類

這個例子中用到的類定義如下:

class Customer
{
public:
    int GetAge() { return m_age; }
    void SetAge(int newAge) { m_age = newAge; }
    std::string GetName() { return m_name; }
    void SetName(std::string newName) { m_name = newName; }

private:
    int m_age;
    std::string m_name;
};

步驟1-JavaScript類

從Customer類派生一個你想在JavaScript中用的新的C++類,或者創(chuàng)建一個包含一個Customer類型成員變量的新類。

給JavaScript用的類得有一個JSClass結構,為此得創(chuàng)建一個JSClass類型的靜態(tài)成員變量,該變量會被其他類用到,因此還得把它聲明為public變量。別的類可以用該結構來判斷對象的類型(見JS_InstanceOf API)。

// JSCustomer.h
class JSCustomer
{
public:
    JSCustomer() : m_pCustomer(NULL) 
    {
    }

    ~JSCustomer()
    {
        delete m_pCustomer;
        m_pCustomer = NULL;
    }

    static JSClass customerClass;

protected:
    void setCustomer(Customer *customer) 
    {
        m_pCustomer = customer; 
    }

    Customer* getCustomer()
    {
        return m_pCustomer; 
    }

private:
    Customer *m_pCustomer;

};


該JSClass結構里包含了JavaScript類的名字、標志位以及給腳本引擎用的回調函數(shù)的名字。舉個例子,腳本引擎使用回調函數(shù)從類中獲取某個屬性值。

在C++類的實現(xiàn)文件中定義JSClass結構如下:

// JSCustomer.cpp
JSClass JSCustomer::customerClass = 
{
    "Customer", JSCLASS_HAS_PRIVATE,
        JS_PropertyStub, JS_PropertyStub,
        JSCustomer::JSGetProperty, JSCustomer::JSSetProperty,
        JS_EnumerateStub, JS_ResolveStub, 
        JS_ConvertStub, JSCustomer::JSDestructor
};


用到的回調函數(shù)是JSCustomer::JSGetProperty,JSCustomer::JSSetProperty和JSCustomer::JSDestructor。腳本引擎調用JSGetProperty獲取屬性值,調用JSSetProperty設置屬性值,調用JSDestructor析構JavaScript對象。

JSCLASS_HAS_PRIVATE標志位會讓腳本引擎分配一些內存,這樣你可以在JavaScript對象中附加一些自定義數(shù)據(jù),比如可以用它來保存類指針。

回調函數(shù)以C++的類靜態(tài)成員函數(shù)方式存在:

static JSBool JSGetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool JSSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
static JSBool JSConstructor(JSContext *cx, JSObject *obj, uintN argc, 
                            jsval *argv, jsval *rval);
static void JSDestructor(JSContext *cx, JSObject *obj);

步驟2-初始化你的JavaScript對象

創(chuàng)建另外一個叫JSInit的靜態(tài)方法,見下面的例子,該方法將在應用程序創(chuàng)建JavaScript runtime時被調用。

static JSObject *JSInit(JSContext *cx, JSObject *obj, JSObject *proto);


JSInit方法的實現(xiàn)大約如下:

JSObject *JSCustomer::JSInit(JSContext *cx, JSObject *obj, JSObject *proto)
{
    JSObject *newObj = JS_InitClass(cx, obj, proto, &customerClass,
        JSCustomer::JSConstructor, 0,
        JSCustomer::customer_properties, JSCustomer::customer_methods,
        NULL, NULL);
    return newObj;
}

對象在腳本中被具象化(譯注:instantiated,簡而言之就是對象new出來的時候)的時候,靜態(tài)方法JSConstructor會被調用。在這個方法中可以用JS_SetPrivate API給該對象附加一些自定義數(shù)據(jù)。

JSBool JSCustomer::JSConstructor(JSContext *cx, JSObject *obj, uintN argc, 
                                 jsval *argv, jsval *rval)
{
    JSCustomer *p = new JSCustomer();

    p->setCustomer(new Customer());
    if ( ! JS_SetPrivate(cx, obj, p) )
        return JS_FALSE;
    *rval = OBJECT_TO_JSVAL(obj);
    return JS_TRUE;
}


JSConstructor構造方法可以帶多個參數(shù),用來初始化類。目前為止已經(jīng)在堆上創(chuàng)建了一個指針,還需要一種途徑來銷毀它,這可以通過JS_Destructor完成:

void JSCustomer::JSDestructor(JSContext *cx, JSObject *obj)
{
    JSCustomer *p = JS_GetPrivate(cx, obj);
    delete p;
    p = NULL;
}

步驟3-添加屬性

添加一個JSPropertySpec類型的靜態(tài)成員數(shù)組來存放屬性信息,同時定義屬性ID的枚舉變量。

static JSPropertySpec customer_properties[];
enum
{
    name_prop,
    age_prop
};

在實現(xiàn)文件中如下初始化該數(shù)組:

JSPropertySpec JSCustomer::customer_properties[] = 

    { "name", name_prop, JSPROP_ENUMERATE },
    { "age", age_prop, JSPROP_ENUMERATE },
    { 0 }
};


數(shù)組的最后一個元素必須為空,其中每個元素是一個帶有3個元素的數(shù)組。第一個元素是給JavaScript用的名字。第二個元素是該屬性的ID,將傳遞給回調函數(shù)。第三個元素是標志位,JSPROP_ENUMERATE代表腳本在枚舉Customer對象的所有屬性時可以看到該屬性,也可以指定JSPROP_READONLY來表明該屬性不允許被腳本程序改變。

現(xiàn)在可以實現(xiàn)該屬性的getting和setting回調函數(shù)了:

JSBool JSCustomer::JSGetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    if (JSVAL_IS_INT(id)) 
    {
        Customer *priv = (Customer *) JS_GetPrivate(cx, obj);
        switch(JSVAL_TO_INT(id))
        {
        case name_prop:

            break;
        case age_prop:
            *vp = INT_TO_JSVAL(priv->getCustomer()->GetAge());
            break;
        }
    }
    return JS_TRUE;
}

JSBool JSCustomer::JSSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
    if (JSVAL_IS_INT(id)) 
    {
        Customer *priv = (Customer *) JS_GetPrivate(cx, obj);
        switch(JSVAL_TO_INT(id))
        {
        case name_prop:
            break;
        case age_prop:
            priv->getCustomer()->SetAge(JSVAL_TO_INT(*vp));
            break;
        }
    }
    return JS_TRUE;
}

建議在屬性的回調函數(shù)中返回JS_TRUE。如果返回JS_FALSE,則當該屬性在對象中沒找到時(腳本引擎)不會進行搜索。

步驟4-添加方法

創(chuàng)建一個JSFunctionSpec類型的靜態(tài)成員數(shù)組:

static JSFunctionSpec customer_methods[];


在實現(xiàn)文件中如下初始化該數(shù)組:

JSFunctionSpec wxJSFrame::wxFrame_methods[] = 
{
    { "computeReduction", computeReduction, 1, 0, 0 },
    { 0 }
};


最后一個元素必須為空,其中每個元素是一個帶有5個元素的數(shù)組。第一個元素是給腳本程序用的方法名稱。第二個是一個全局或者靜態(tài)成員函數(shù)的名稱。第三個是該方法的參數(shù)個數(shù)。最后兩個可以忽略。

在類中創(chuàng)建一個靜態(tài)方法:

static JSBool computeReduction(JSContext *cx, JSObject *obj, uintN argc, 
                               jsval *argv, jsval *rval);


該函數(shù)成功時返回JS_TRUE,否則返回JS_FALSE。注意真正的JavaScript方法的返回值保存在rval參數(shù)中。

該方法的一個實現(xiàn)例子:

JSBool JSCustomer::computeReduction(JSContext *cx, JSObject *obj, uintN argc, 
                                    jsval *argv, jsval *rval)
{
    JSCustomer *p = JS_GetPrivate(cx, obj);
    if ( p->getCustomer()->GetAge() < 25 )
        *rval = INT_TO_JSVAL(10);
    else
        *rval = INT_TO_JSVAL(5);
    return JS_TRUE;
}

使用例子

下面的腳本使用了前面創(chuàng)建的對象:

var c = new Customer();
c.name = "Franky";
c.age = 32;
var reduction = c.computeReduction();

別忘了在創(chuàng)建context時初始化JavaScript對象:

JSObject *obj = JSCustomer::JSInit(cx, global);

“在C++中怎么執(zhí)行JavaScript程序”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質量的實用文章!


本文題目:在C++中怎么執(zhí)行JavaScript程序-創(chuàng)新互聯(lián)
文章URL:http://weahome.cn/article/djscog.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部