Google V8基础入门

写这篇文章前,大家可以在Google上找到很多Google v8基础入门的文章,例如:
IBM DeveloperWorks中国
https://www.ibm.com/developerworks/cn/opensource/os-cn-v8engine/
Legend(谭海燕)的专栏
http://blog.csdn.net/feiyinzilgd/article/details/8248448
headool的专栏
http://blog.csdn.net/headool/article/list/2
等等…

但之前的一些基础教程由于v8的版本有些低,在新版的v8接口下编绎通不过,所以在此就整理了一下,自己记录学习了,理论相关的知识我就不整理,上面的博文说得比较详细了,直接上代码

全局变量,供JS访问

static int globalValue = 0;
static Isolate *globalIsolate = NULL;

void globalGetter(Local<String> property, PropertyCallbackInfo<Value>& info)
{
    info.GetReturnValue().Set(v8::Integer::New(globalIsolate, globalValue));
    printf("js read \"globalValue\"\n");
}

void globalSetter(Local<String> property, Local<Value> value, const PropertyCallbackInfo<void>& info)
{
    globalValue = value->Int32Value();
    printf("js change \"globalValue: %d\"\n", globalValue);
}

int main(int argc, const char * argv[])
{
    v8::V8::InitializeICU();
    v8::V8::Initialize();
    
    globalIsolate = Isolate::New();
    
    Isolate::Scope isolate_scope(globalIsolate);
    HandleScope handle_scope(globalIsolate);
    
    v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(globalIsolate);
    //全局变量,通过Getter,Setter方法访问和设置
    global->SetAccessor(v8::String::NewFromUtf8(globalIsolate, "globalValue"), (AccessorGetterCallback)globalGetter, (AccessorSetterCallback)globalSetter);
    
    Local<Context> context = Context::New(globalIsolate, NULL, global);
    Context::Scope context_scope(context);
    
    //编写JS源代码,编绎执行
    Local<String> source = String::NewFromUtf8(globalIsolate, "var tmpValue = globalValue; globalValue = 21; ");
    Local<Script> script = Script::Compile(source);
    Local<Value> result = script->Run();
    
    String::Utf8Value utf8(result);
    printf("Script Run Result: %s\n", *utf8);

    v8::V8::Dispose();    
    return 0;
}
输出
js read "globalValue"
js change "globalValue: 21"
Script Run Result: 21

全局函数,供JS调用

void globalFun(const v8::FunctionCallbackInfo<Value> &args)
{
    printf("js call C++ \"globalFun\"\n");
}

int main(int argc, const char * argv[])
{
    //省略部份声明代码,参考上面
    Local<FunctionTemplate> globalFunTemplate = v8::FunctionTemplate::New(globalIsolate, (FunctionCallback)globalFun);
    global->Set(v8::String::NewFromUtf8(globalIsolate, "globalFun"), globalFunTemplate);

    Local<String> source = String::NewFromUtf8(globalIsolate, "globalFun();");
    Local<Script> script = Script::Compile(source);
    Local<Value> result = script->Run();    
}
输出:
js call C++ "globalFun"

JS访问C++类及方法

class Person{
private:
    String::Utf8Value *firstName;
    String::Utf8Value *lastName;
public:
    Person(Handle<v8::Value> firstValue, Handle<v8::Value> LastValue){
        this->firstName = new String::Utf8Value(firstValue);
        this->lastName = new String::Utf8Value(LastValue);
    }
    
    ~Person(){
        delete firstName;
        delete lastName;
    }
    
    void sayHello(){
        printf("Hello, My Name is: \"%s %s\"\n", **firstName, **lastName);
    }
};

//JS访问Person.sayHell转换函数
void Person_SayHello(const v8::FunctionCallbackInfo<Value> &args)
{
    Local<Object> self = args.Holder();
    Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
    void *ptr = wrap->Value();
    static_cast<Person*>(ptr)->sayHello();
}

//JS创建Person转换函数
void createPerson(const v8::FunctionCallbackInfo<Value> &args)
{
    if (args.Length() >= 2){
        Local<Object> self = args.Holder();
        Person *person = new Person(args[0], args[1]);
        
        self->SetInternalField(0, External::New(globalIsolate, person));
        args.GetReturnValue().Set(self);
    }
}

int main(int argc, const char * argv[])
{
    //省略部份声明代码,参考上面
    v8::Local<FunctionTemplate> personClass = v8::FunctionTemplate::New(globalIsolate, (FunctionCallback)createPerson);
    personClass->SetClassName(v8::String::NewFromUtf8(globalIsolate, "Person"));
    v8::Handle<ObjectTemplate>p_Prototype = personClass->PrototypeTemplate();
    p_Prototype->Set(String::NewFromUtf8(globalIsolate, "sayHello"), FunctionTemplate::New(globalIsolate, Person_SayHello));
    v8::Handle<ObjectTemplate> personInst = personClass->InstanceTemplate();
    personInst->SetInternalFieldCount(1);
    global->Set(v8::String::NewFromUtf8(globalIsolate, "Person"), personClass);

    Local<String> source = String::NewFromUtf8(globalIsolate, "var p = new Person('Kevin', 'Lu'); p.sayHello();");
    Local<Script> script = Script::Compile(source);
    Local<Value> result = script->Run();    
}
输出:
Hello, My Name is: "Kevin Lu"

C++访问JS

void testCallJS()
{
    v8::Isolate *callJSISolate = v8::Isolate::New();
    v8::Isolate::Scope isolate_scope(callJSISolate);
    
    HandleScope handle_scope(callJSISolate);
    v8::Handle<Context> context = v8::Context::New(callJSISolate);
    
    v8::Context::Scope contextScope(context);
    //JS创建Person对象,并添加getName方法,返回name
    v8::Local<String> source = String::NewFromUtf8(callJSISolate, "function Person() { this.name = 'Kevin'; } Person.prototype.getName = function () { return this.name; }; var p = new Person();");
    
    v8::Local<Script> script = v8::Script::Compile(source);
    script->Run();
    
    v8::Handle<Value> data_p = context->Global()->Get(String::NewFromUtf8(callJSISolate, "p"));
    v8::Handle<Object> object_p = Handle<Object>::Cast(data_p);
    v8::Handle<Function> getName = Handle<Function>::Cast(object_p->Get(String::NewFromUtf8(callJSISolate, "getName")));
    Handle<Value> value = getName->Call(object_p, 0, NULL);
    
    String::Utf8Value utf8(value);
    printf("call js function result: %s\n", *utf8);
}
输出:
call js function result: Kevin

上面例子源代码:点这里

有了这些基础的知识,大家可以尝试写一些应用了,更多的知识可以直接去参考基于Google v8的Node.js、io.js、fibjs的源代码