使用訪問器訪問 C++ 對象
為我們的類設置環(huán)境
怎樣使用C++把一個類映射成為 JavaScript?首先來看看如下的例子:
//Sample class mapped to v8
class Point
{
public:
//constructor
Point(int x, int y):x_(x),y_(y){}
//internal class functions
//just increment x_
void Function_A(){++x_; }
//increment x_ by the amount
void Function_B(int vlr){x_+=vlr;}
//variables
int x_;
};
為了保證整個類映射后完全基于 JavaScript,我們對類的成員函數(shù)和變量都做映射。第一步,在上下文環(huán)境(context)中映射一個類模板:
Handle<FunctionTemplate> point_templ = FunctionTemplate::New();
point_templ->SetClassName(String::New("Point"));
從字面上似乎看出:我們只是創(chuàng)建了一個“函數(shù)(function)”模板,但實際上它能夠被看作一個類。它的名字是“Point”,我們將會在后面用到。
然后,通過訪問原型(prototype) 類模板,我們能為這個類添加內建的方法:
Handle<ObjectTemplate> point_proto = point_templ->PrototypeTemplate();
point_proto->Set("method_a", FunctionTemplate::New(PointMethod_A));
point_proto->Set("method_b", FunctionTemplate::New(PointMethod_B));
類能通過上面的代碼“知道”它有兩個方法。但這仍然是類的原型,我們必須要實例化這個類之后,才能使用這兩個方法。
Handle<ObjectTemplate> point_inst = point_templ->InstanceTemplate();
point_inst->SetInternalFieldCount(1);
SetInternalFieldCount 函數(shù)為類指針申請空間(在后面會再一次提到)。一旦有了類的實例,我們就能為類中的變量添加訪問器了:
point_inst->SetAccessor(String::New("x"), GetPointX, SetPointX);
至此,舞臺算是搭好了,主角該上場了:
Point* p = new Point(0, 0);
新類已經建好了,但只能在C++中訪問。要對其進行訪問,我們需要:
Handle<Function> point_ctor = point_templ->GetFunction();
Local<Object> obj = point_ctor->NewInstance();
obj->SetInternalField(0, External::New(p));
GetFunction 返回 point 的構造器,有了它,我們可以使用 NewInstance 函數(shù)來創(chuàng)建一個新的實例。然后,使用類指針來設置內部域(這個域的空間我們在前面已經使用 SetInternalFieldCount 函數(shù)申請好了)。這樣一來,JavaScript 就能通過指針訪問該對象。
有一點我們漏掉了,我們想從 JavaScript 中訪問它,但只有類模板和實例,沒有名字:
context->Global()->Set(String::New("point"), obj);
最后一步將“point”這個名字和 obj 實例聯(lián)系起來。到這里,我們僅僅是完成了在腳本中使用“point”名字來創(chuàng)建 Point 類的過程。
在 JavaScript 中訪問類方法
這里講的并不是我們怎樣在 Point 類中訪問 Function_A……
先來看看回調函數(shù) PointMethod_A:
Handle<Value> PointMethod_A(const Arguments& args)
{
Local<Object> self = args.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
static_cast<Point*>(ptr)->Function_A();
return Integer::New(static_cast<Point*>(ptr)->x_);
}
和普通的訪問器類似,我們需對參數(shù)進行操作。而且,要能訪問我們自己的類,還必須得從內部域中獲取相關的類指針。在將內部域映射到“wrap”之后,就可以通過獲取它的“值(Value)”來得到類指針,然后再進行類型轉換。得到“point”類指針之后,可以通過它來調用 method_a ,method_a 來調用回調函數(shù) PointMethod_A。
示例 v8_embedded_demo_with_object.zip (Visual C++ Express 2008 )完整的包含了上述各個步驟。
最后,我非常希望這篇文章能對你有所幫助。如果感覺文中有錯誤或者不清楚的地方,歡迎和我進行討論~~