首先到google开发者网站上下载v8源码,并按照说明进行编译。
在v8中,编译和执行的js代码需要依付于一个空间(上下文)。上下文由Context::New创建。
static Persistent<Context> New(
ExtensionConfiguration* extensions = NULL,
Handle<ObjectTemplate> global_template = Handle<ObjectTemplate>(),
Handle<Value> global_object = Handle<Value>());
其中,extensions表示要增加到上下文的额外配置。global_template指定产生上下文内部对象的对象模板。global_object是要重用的上下文内部对象(该对象是以前由Context::New创建出来的上下文内部对象,且其对象模板必须和global_template相同)。要注意的是,如果指定了global_object,则该global_object除了对象标识会被保留外,其它状态全部重置。
上下文就是js中通过对象模拟出来的命名空间:
function namespace_template()
{
return {};
}
var Namespace = new namespace_template();
with(Namespace)
{
...
};
Persistent<Context> context = Context::New(NULL, namespace_template,NULL);//此处的namespace_template仅表示对应关系
Local<Object> Namespace = context->Global();
要使用上下文,需调用:context->Enter();
接下来,编译运行js代码:
Local<Script> script = Script::Compile(String::New("function add(a, b){return a+b;}"));
script->Run();
Script::Compile:在当前上下文中编译js代码。调用Run时,使用的是Script::Compile时的上下文。
Script::New:独立编译js代码。调用Run时,使用的是调用Run时的上下文。
调用JS中的函数:
Local<Value> value_add = Namespace->Get(String::New("add"));
ASSERT(value_add->IsFunction());
Local<Function> fun_add = Local<Function>::Cast(value_add);
Handle<Value> args[2];
args[0] = Uint32::New(1);
args[1] = Uint32::New(2);
Local<Value> result_add = fun_add->Call(Namespace, 2, args);
ASSERT(result_add->IsUint32());
uint32_t ui_result_add = result_add->Uint32Value();
绑定函数(让js调用VC中的代码):
假设VC中的代码为:
int ave(int a, int b, int c){return (a+b+c)/3;}
希望在js中可直接进行如下调用:
var ave_value = ave(10, 20, 3.);
v8无法将C/C++中的函数直接导出,需要一定的转换:
Handle<Value> ave_js(const Arguments& args)
{
if(args.Length() < 3) return Undefined();
int ave_value = ave(args[0]->Int32Value(), args[1]->Int32Value(), args[2]->Int32Value());
return Int32::New(ave_value);
}
Namespace->Set(String::New("ave"), FunctionTemplate::New(ave_js)->GetFunction());
绑定对象:
假设VC中有一个CRectangle类对象rectangle(在实际使用中要考虑生命周期):
class CRectangle
{
public:
int w;
int h;
int Area() const{return w * h;}
}rectangle;
希望在js中进行如下调用:
rectangle.w = 10;
rectangle.h = 20;
var area = rectangle.Area();
实现:
Handle<Value> Rectangle_Area(const Arguments& args)
{
Handle<External> field = Handle<External>::Cast(args.Holder()->GetInternalField(0));
void* raw_rectangle_ptr = field->Value();
CRectangle* pRectangle = static_cast<CRectangle*>(raw_rectangle_ptr);
int area_value = pRectangle->Area();
return Int32::New(area_value);
}
Handle<Value> Rectangle_Getter(Local<String> property, const AccessorInfo& info)
{
Local<String> sw = String::New("w");
Local<String> sh = String::New("h");
Local<String> sarea = String::New("Area");
Handle<External> field = Handle<External>::Cast(info.Holder()->GetInternalField(0));
void* raw_rectangle_ptr = field->Value();
CRectangle* pRectangle = static_cast<CRectangle*>(raw_rectangle_ptr);
if(property->StrictEquals(sw)) return Int32::New(pRectangle->w);
if(property->StrictEquals(sh)) return Int32::New(pRectangle->h);
if(property->StrictEquals(sarea))
{
static Local<Function> Area_Fun = FunctionTemplate::New(Rectangle_Area)->GetFunction();
return Area_Fun;
}
return Undefined();
}
Handle<Value> Rectangle_Setter(Local<String> property, Local<Value> value, const AccessorInfo& info)
{
Local<String> sw = String::New("w");
Local<String> sh = String::New("h");
Local<String> sarea = String::New("Area");
Handle<External> field = Handle<External>::Cast(info.Holder()->GetInternalField(0)) ;
void* raw_rectangle_ptr = field->Value();
CRectangle* pRectangle = static_cast<CRectangle*>(raw_rectangle_ptr);
if(property->StrictEquals(sw)) return Int32::New(pRectangle->w = value->Int32Value());
if(property->StrictEquals(sh)) return Int32::New(pRectangle->h = value->Int32Value());
return Undefined();
}
Local<ObjectTemplate> rectangle_template = ObjectTemplate::New();
rectangle_template->SetInternalFieldCount(1);
rectangle_template->SetNamedPropertyHandler(Rectangle_Getter, Rectangle_Setter);
rectangle_template->Set(String::New("w"), Int32::New(0));//由于设置了属性访问器和设置器,传入的Int32::New(0)不会被使用
rectangle_template->Set(String::New("h"), Int32::New(0));//由于设置了属性访问器和设置器,传入的Int32::New(0)不会被使用
rectangle_template->Set(String::New("Area"), Int32::New(0));//由于设置了属性访问器和设置器,传入的Int32::New(0)不会被使用
Local<Object> rectangle_obj = rectangle_template->NewInstance();
rectangle_obj->SetInternalField(0, External::New(&rectangle));
Namespace->Set(String::New("rectangle"), rectangle_obj);
导出类(js中的构造函数):
希望在js中生成一个Rectangle类:
function Rectangle(w, h)
{
this.w = w;
this.h = h;
this.Area = function(){return this.w * this.h;}
}
进行如下调用:
var rectangle = new Rectangle(10, 20);
var area = rectangle.Area();
rectangle.w = 1;
rectangle.h = 2;
area = rectangle.Area();
实现:
Handle<Value> CRectangle_Area(const Arguments& args)
{
Local< Object > pThis = args.This();
int w = pThis->Get(String::New("w"))->Int32Value();
int h = pThis->Get(String::New("h"))->Int32Value();
return Int32::New(w*h);
}
Handle<Value> Rectangle_InvocationCallback(const Arguments& args)
{
Local< Object > pThis = args.This() ;
int w = 0, h = 0;
if(args.Length() > 0) w = args[0]->Int32Value();
if(args.Length() > 1) h = args[1]->Int32Value();
pThis->Set(String::New("w"), Int32::New(w));
pThis->Set(String::New("h"), Int32::New(h));
return pThis;
}
Local< FunctionTemplate > Rectangle_template = FunctionTemplate::New();
Local<ObjectTemplate> Rectangle_instance_template = Rectangle_template->InstanceTemplate();
Rectangle_instance_template->SetCallAsFunctionHandler(Rectangle_InvocationCallback);
Rectangle_instance_template->Set("w", Number::New(0));
Rectangle_instance_template->Set("h", Number::New(0));
Rectangle_instance_template->Set("Area", FunctionTemplate::New(CRectangle_Area));
Local<Function> Rectangle_function = Rectangle_template->GetFunction();
Local<Object> Rectangle = Rectangle_function->NewInstance();
Namespace->Set(String::New("Rectangle"), Rectangle);
完整源码请查看本人发布的资源