欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
在C++中應用Google Chrome腳本引擎-V8

在C++中應用Google Chrome腳本引擎——V8

原文地址:http://www.codeproject.com/KB/library/Using_V8_Javascript_VM.aspx

介紹

誰(shuí)不想知道虛擬機是怎樣工作的?不過(guò),比起自己寫(xiě)一個(gè)虛擬機,更好的辦法是使用大公司的產(chǎn)品。在這篇文章中,我將介紹如何在你的程序中使用V8——谷歌瀏覽器(Chrome)所使用的開(kāi)源JavaScript引擎。

背景

這里的代碼使用V8作為嵌入庫來(lái)執行JavaScript代碼。要取得庫源碼和其它信息,可以瀏覽V8開(kāi)發(fā)者頁(yè)面。想有效地應用V8,你需要了解C/C++JavaScript。

使用

我們來(lái)看看演示中有哪些東西:

·                     如何使用V8API來(lái)執行JavaScript腳本。

·                     如何存取腳本中的整數和字符串。

·                     如何建立可被腳本調用的自定義函數。

·                     如何建立可被腳本調用的自定義類(lèi)。

首先,我們一起了解一下怎樣初始化V8。這是嵌入V8引擎的簡(jiǎn)單例子:

1.                #include <v8.h>

2.                using namespace v8;

3.                int main(int argc, char* argv[]) {

4.                  // Create a stack-allocated handle scope.

5.                  HandleScope handle_scope;

6.                  // Create a new context.

7.                  Handle<Context> context = Context::New();

8.                  // Enter the created context for compiling and

9.                  // running the hello world script.

10.              Context::Scope context_scope(context);

11.              // Create a string containing the JavaScript source code.

12.              Handle<String> source = String::New("'Hello' + ', World!'");

13.              // Compile the source code.

14.              Handle<Script> script = Script::Compile(source);

15.              // Run the script to get the result.

16.              Handle<Value> result = script->Run();

17.              // Convert the result to an ASCII string and print it.

18.              String::AsciiValue ascii(result);

19.              printf("%s ", *ascii);

20.              return 0;

21.            }

好了,不過(guò)這還不能說(shuō)明怎樣讓我們控制腳本中的變量和函數。

全局模型(The Global Template

首先,我們需要一個(gè)全局模型來(lái)掌控我們所做的修改:

1.                v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();

這里建立了一個(gè)新的全局模型來(lái)管理我們的上下文(context)和定制。在V8里,每個(gè)上下文是分開(kāi)的,它們有自己的全局模型。一個(gè)上下文就是一個(gè)獨立的執行環(huán)境,相互之間沒(méi)有關(guān)聯(lián),JavaScript運行于其中一個(gè)實(shí)例之中。

自定義函數

接下來(lái),我們加入一個(gè)名為"plus"的自定義函數:

1.                // plus function implementation - Add two numbers

2.                v8::Handle<v8::Value> Plus(const v8::Arguments& args)

3.                {

4.                    unsigned int A = args[0]->Uint32Value();

5.                    unsigned int B = args[1]->Uint32Value();

6.                    return v8_uint32(A +  B);

7.                }

8.                //...

9.                //associates plus on script to the Plus function

10.            global->Set(v8::String::New("plus"), v8::FunctionTemplate::New(Plus));

自定義函數必須以const v8::Arguments&作為參數并返回v8::Handle<v8::Value>。我們把這個(gè)函數加入到模型中,關(guān)聯(lián)名稱(chēng)"plus"到回調Plus?,F在,在腳本中每次調用"plus",我們的Plus函數就會(huì )被調用。這個(gè)函數只是返回兩個(gè)參數的和。

現在我們可以在JavaScript里使用這個(gè)自定義函數了:

plus(120,44); 

在腳本里也可以得到函數的返回值:

x = plus(1,2);

if( x == 3){

   // do something important here!

}

訪(fǎng)問(wèn)器(Accessor)——存取腳本中的變量

現在,我們可以建立函數了...不過(guò)如果我們可以在腳本外定義一些東西豈不是更酷?Let's do it! V8里有個(gè)東東稱(chēng)為存取器(Accessor),使用它,我們可以關(guān)聯(lián)一個(gè)名稱(chēng)到一對Get/Set函數上,V8會(huì )用它來(lái)存取腳本中的變量。

1.                global->SetAccessor(v8::String::New("x"), XGetter, XSetter);

這行代碼關(guān)聯(lián)名稱(chēng)"x"XGetterXSetter函數。這樣在腳本中每次讀取到"x"變量時(shí)都會(huì )調用XGetter,每次更新"x"變量時(shí)會(huì )調用XSetter。下面是這兩個(gè)函數的代碼:

1.                //the x variable!

2.                int x;

3.                //get the value of x variable inside javascript

4.                static v8::Handle<v8::Value> XGetter( v8::Local<v8::String> name,

5.                                  const v8::AccessorInfo& info) {

6.                  return  v8::Number::New(x);

7.                }

8.                //set the value of x variable inside javascript

9.                static void XSetter( v8::Local<v8::String> name,

10.                   v8::Local<v8::Value> value, const v8::AccessorInfo& info) {

11.              x = value->Int32Value();

12.            }

XGetter里我們把"x"轉換成V8喜歡的數值類(lèi)型。XSetter里,我們把傳入的參數轉換成整數,Int32Value是基本類(lèi)型轉換函數的一員,還有NumberValue對應double、BooleanValue對應bool,等。

現在,我們可以為字符串做相同的操作:

1.                //the username accessible on c++ and inside the script

2.                char username[1024];

3.                //get the value of username variable inside javascript

4.                v8::Handle<v8::Value> userGetter(v8::Local<v8::String> name,

5.                           const v8::AccessorInfo& info) {

6.                    return v8::String::New((char*)&username,strlen((char*)&username));

7.                }

8.                //set the value of username variable inside javascript

9.                void userSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value,

10.                const v8::AccessorInfo& info) {

11.                v8::Local<v8::String> s = value->ToString();

12.                s->WriteAscii((char*)&username);

13.            }

對于字符串,有一點(diǎn)點(diǎn)不同,"userGetter"XGetter做的一樣,不過(guò)userSetter要先用ToString方法取得內部字符串,然后用WriteAscii函數把內容寫(xiě)到我們指定的內存中?,F在,加入存取器:

1.                //create accessor for string username

2.                global->SetAccessor(v8::String::New("user"),userGetter,userSetter);

打印輸出

"print"函數是另一個(gè)自定義函數,它通過(guò)"printf"輸出所有的參數內容。和之前的"plus"函數一樣,我們要在全局模型中注冊這個(gè)函數:

1.                //associates print on script to the Print function

2.                global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));

實(shí)現"print"函數

1.                // The callback that is invoked by v8 whenever the JavaScript 'print'

2.                // function is called. Prints its arguments on stdout separated by

3.                // spaces and ending with a newline.

4.                v8::Handle<v8::Value> Print(const v8::Arguments& args) {

5.                    bool first = true;

6.                    for (int i = 0; i < args.Length(); i++)

7.                    {

8.                        v8::HandleScope handle_scope;

9.                        if (first)

10.                    {

11.                        first = false;

12.                    }

13.                    else

14.                    {

15.                        printf(" ");

16.                    }

17.                    //convert the args[i] type to normal char* string

18.                    v8::String::AsciiValue str(args[i]);

19.                    printf("%s", *str);

20.                }

21.                printf(" ");

22.                //returning Undefined is the same as returning void...

23.                return v8::Undefined();

24.            }

這里,為每個(gè)參數都構建了v8::String::AsciiValue對象:數據的char*表示。通過(guò)它,我們就可以把所有類(lèi)型都轉換成字符串并打印出來(lái)。

JavaScript演示

在演示程序里,我們有一個(gè)簡(jiǎn)單的JavaScript腳本,調用了迄今為止我們建立的所有東西:

print("begin script");

print(script executed by  + user);

if ( user == "John Doe"){

    print("\tuser name is invalid. Changing name to Chuck Norris");

    user = "Chuck Norris";

}

print("123 plus 27 = " + plus(123,27));

x = plus(3456789,6543211);

print("end script");

 

存取C++對象

為我們的類(lèi)準備環(huán)境

如果用C++把一個(gè)類(lèi)映射到JavaScript中去?放一個(gè)演示用的類(lèi)上來(lái)先:

1.                //Sample class mapped to v8

2.                class Point

3.                {

4.                public:

5.                    //constructor

6.                    Point(int x, int y):x_(x),y_(y){}

7.                 

8.                    //internal class functions

9.                    //just increment x_

10.                void Function_A(){++x_;    }

11.             

12.                //increment x_ by the amount

13.                void Function_B(int vlr){x_+=vlr;}

14.             

15.                //variables

16.                int x_;

17.            };

為了把這個(gè)類(lèi)完全嵌入腳本中,我們需要映射類(lèi)成員函數和類(lèi)成員變量。第一步是在我們的上下文中映射一個(gè)類(lèi)模型(class template):

1.                Handle<FunctionTemplate> point_templ = FunctionTemplate::New();

2.                point_templ->SetClassName(String::New("Point"));

我們建立了一個(gè)"函數"模型[FunctionTemplate],但這里應該把它看成類(lèi)。

然后,我們通過(guò)原型模型(Prototype Template)加入內建的類(lèi)方法:

1.                Handle<ObjectTemplate> point_proto = point_templ->PrototypeTemplate();

2.                point_proto->Set("method_a", FunctionTemplate::New(PointMethod_A));

3.                point_proto->Set("method_b", FunctionTemplate::New(PointMethod_B));

接下來(lái),類(lèi)有了兩個(gè)方法和對應的回調。但它們目前只在原型中,沒(méi)有類(lèi)實(shí)例訪(fǎng)問(wèn)器我們還不能使用它們。

1.                Handle<ObjectTemplate> point_inst = point_templ->InstanceTemplate();

2.                point_inst->SetInternalFieldCount(1);

SetInternalFieldCount函數為C++類(lèi)建立一個(gè)空間(后面會(huì )用到)。

現在,我們有了類(lèi)實(shí)例,加入訪(fǎng)問(wèn)器以訪(fǎng)問(wèn)內部變量:

1.                point_inst->SetAccessor(String::New("x"), GetPointX, SetPointX);

接著(zhù),土壤準備好了,開(kāi)始播種:

1.                Point* p = new Point(0, 0);

新對象建立好了,目前只能在C++中使用,要放到腳本里,我們還要下面的代碼:

1.                Handle<Function> point_ctor = point_templ->GetFunction();

2.                Local<Object> obj = point_ctor->NewInstance();

3.                obj->SetInternalField(0, External::New(p));

好了,GetFunction返回一個(gè)point構造器(JavaScript方面), 通過(guò)它,我們可以用NewInstance生成一個(gè)新的實(shí)例。然后,用Point對象指針設置我們的內部域(我們前面用SetInternalFieldCount建立的空間),JavaScript可以通過(guò)這個(gè)指針存取對象。

還少了一步,我們只有類(lèi)模型和實(shí)例,但還缺一個(gè)名字來(lái)存取它:

1.                context->Global()->Set(String::New("point"), obj);

JavaScript里訪(fǎng)問(wèn)類(lèi)方法

最后,我們還要解釋一下怎樣在Point類(lèi)中訪(fǎng)問(wèn)Function_A...

讓我們看看PointMethod_A回調:

1.                Handle<Value> PointMethod_A(const Arguments& args)

2.                {

3.                    Local<Object> self = args.Holder();

4.                    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));

5.                    void* ptr = wrap->Value();

6.                    static_cast<Point*>(ptr)->Function_A();

7.                    return Integer::New(static_cast<Point*>(ptr)->x_);

8.                }

和普通訪(fǎng)問(wèn)器一樣,我們必須處理參數。要訪(fǎng)問(wèn)我們的類(lèi),必須從內部域(第一個(gè))中取得類(lèi)指針。把內部域映射到"wrap"之后,我們使用它的"value"方法取得類(lèi)指針。

其它

希望這篇文章對你有所幫助,如果發(fā)現文章有誤,請不吝賜教。

Google的V8參考文檔

許可

This article, along with any associated source code and files, is licensed under A Public Domain dedication

關(guān)于作者

GabrielWF

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Google V8 引擎 原理詳解
關(guān)于V8 JavaScript Engine的使用方法研究(二)
V8 JavaScript 引擎 – 嵌入者指南
JavaScript引擎研究與C、C++與互調用
Chromium C++與JS之間互調
C++ 沉思錄——句柄——智能指針改寫(xiě)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久