基于什么原因略!

1. 脚本引擎的基本功能

V8只是一个JS引擎。去除它的特点功能出处,它必须要实现JS引擎的几个基础功能:

脚本执行:
脚本可能是一个表达式;一段js代码;或者一个文件
执行表达式返回js表达式对应的值
C++来取设JS的内容
获取JS内容的数据(包括基础数据类型、数组、日期等)、对象(类的一个实例)、类或函数
设置JS内容的数据
JS来取设C++的内容
C++为js动态添加类(例如:Date,可以通过new Date()来创建任意多个对象)
C++为js动态添加全局对象(例如:Math,可以直接调用其全局方法如Math.min)
我们的目的是先学会怎么用,再去想为什么!

2. V8 脚本引擎基本功能实现

带着这几个目的去使用V8,找遍网上资料,发现很少有覆盖周全的。其实翻来覆去就是那几个资料,理论派居多;最可气的是按照那些例子去跑,怎么都会运行错误;而且在关键的地方全按照google伪代码例子照搬。不过理论派的阐述确实很一本正经;很精辟。也感谢先行者!

2. 1 V8之脚本运行
2.1.1 获取字符串:

void test_String()
{
Handle<String> source = String::New("'Hello' + ', World!'");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();

String::AsciiValue ascii(result);
printf("%s\n", *ascii);
}
>>> Hello,World!

2.1.2 获取数组:

void test_Array()
{
Handle<String> source = String::New("[1, 2, 'hello', 6+5]");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();

String::AsciiValue ascii(result);
printf("%s\n", *ascii);
}
>>> 1,2,hello,11

2. 2 V8之C++取设JS
2.2.1 获取成员之数据

void test_getjs_data(Handle<Context> pContext)
{
Handle<String> source = String::New("var s1 = 8+5;");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();
Handle<String> js_data = String::New("s1");
Handle<Value> js_data_value = pContext->Global()->Get(js_data);

String::AsciiValue ascii(js_data_value);
printf("%s\n", *ascii);
}
>>> 13

2.2.2 获取成员之全局对象

void test_getjs_dataofObject(Handle<Context> pContext)
{
Handle<String> source = String::New("function Point(x,y){this.x=x; this.y=y;} var pt=new Point(10,20);");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();

Handle<String> js_data = String::New("pt");
Handle<Value> js_data_value = pContext->Global()->Get(js_data);

// Convert the result to an ASCII string and print it.
{
String::AsciiValue ascii(js_data_value);
printf("pt = %s\n", *ascii);
}
Handle<Object> js_data_object = Handle<Object>::Cast(js_data_value);

Handle<Value> key = String::New("x");
Handle<Value> objX = js_data_object->Get(key);
{
String::AsciiValue ascii(objX);
printf("pt.x = %s\n", *ascii);
}
}
>>> pt = [object Object]
pt.x = 10

2.2.3 获取js 类

void test_getjs_dataofObjectClass(Handle<Context> pContext)
{
Handle<String> source = String::New("function Point(x,y){this.x=x; this.y=y;} Point.prototype.show=function(){return '(x,y) = '+this.x+','+this.y;}");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();

Handle<String> js_data = String::New("Point");
Handle<Value> js_data_value = pContext->Global()->Get(js_data);

// Convert the result to an ASCII string and print it.
{
String::AsciiValue ascii(js_data_value);
printf("Point = %s\n", *ascii);
}

bool bIsFunction = js_data_value->IsFunction();
if(bIsFunction)
{
printf("Point is function\n");
}

bool bIsObject = js_data_value->IsObject();
if(bIsObject)
{
printf("Point is object\n");
}

Handle<Object> js_data_object = Handle<Object>::Cast(js_data_value);
// var newObj = new Point(1,2);
Handle<Value> argv[2] ;
argv[0] = Int32::New(1);
argv[1] = Int32::New(2);
Handle<Value> newObj = js_data_object->CallAsConstructor(2, argv);
{
bool bIsFunction = newObj->IsFunction();
if(bIsFunction) //-false-
{
printf("newObj is function\n");
}

bool bIsObject = newObj->IsObject();
if(bIsObject) //-true-
{
printf("newObj is object\n");
}
}

// newObj.show();
{
Handle<Object> obj = Handle<Object>::Cast(newObj);
Handle<String> js_func_name = String::New("show");
Handle<Value> js_func_ref = obj->Get(js_func_name);

Handle<Function> js_func = Handle<Function>::Cast(js_func_ref);
js_data_value = js_func->Call(obj, 0, NULL) ;

String::AsciiValue ascii(js_data_value);
printf("newObj.show() = %s\n", *ascii);
}
}
>>> Point = function Point(x,y){this.x=x; this.y=y;}
Point is function
Point is object
newObj is object
newObj.show() = (x,y) = 1,2

2. 3 V8之JS取设C++
2.3.0 js 和 C++的关联

c++ 和 js对应。特别是为达到能在Js中使用var obj = new CObject(),参照CreateObjectToJs方法

void test_getc_loadObjectTemplate(Handle<ObjectTemplate> pObj)
{
//-load c++'s data-
pObj->SetAccessor(String::New("x"), XGetter, XSetter);

//-load c++'s function-
pObj->Set(String::New("setColor"),FunctionTemplate::New(set_color));

//-load c++'s class-
CreateObjectToJs(pObj);
}

Point* NewPointFunction(const Arguments & args)
{
if(args.Length()==2)
{
Local<Value> v1 = args[0];
Local<Value> v2 = args[1];

return new Point( v1->Int32Value(), v2->Int32Value() );
}
else
return new Point();
}

void PointWeakExternalReferenceCallback(Persistent<Value>, void* parameter)
{
if (Point* cpp_object = static_cast<Point*>(parameter))
delete cpp_object;
}

Persistent<External> NewWeakExternalPoint(void* parameter)
{
Persistent<External> ret = Persistent<External>::New(External::New(parameter));
ret.MakeWeak(parameter, PointWeakExternalReferenceCallback);
return ret;
}

Handle<Value> PointFunctionInvocationCallback(const Arguments &args)
{
if (!args.IsConstructCall())
return Undefined();

Point* cpp_object = NewPointFunction(args);
if (!cpp_object)
return ThrowException(String::New("Can not create Object in C++"));

args.Holder()->SetInternalField(0, NewWeakExternalPoint(cpp_object));
return Undefined();
}

void CreateObjectToJs(Handle<ObjectTemplate> pObj)
{
Point* p = new Point(0, 0);
Handle<FunctionTemplate> point_templ = FunctionTemplate::New(&PointFunctionInvocationCallback, External::New(p));
point_templ->SetClassName(String::New("Point"));
point_templ->InstanceTemplate()->SetInternalFieldCount(1);

Handle<ObjectTemplate> point_proto = point_templ->PrototypeTemplate();
point_proto->SetAccessor(String::New("x"), GetPointX, SetPointX);
point_proto->SetAccessor(String::New("y"), GetPointY, SetPointY);
point_proto->Set(String::New("show"), FunctionTemplate::New(ShowPoint));

pObj->Set(String::New("Point"), point_templ);
}

2.3.1 全局函数

c++:
Handle<Value> set_color(const Arguments & args)
{
Handle<Value> rtn;
if(args.Length() == 3)
{
int r = args[0]->Int32Value();
int g = args[1]->Int32Value();
int b = args[2]->Int32Value();

char szTmp[80] = "";
_stprintf(szTmp,"RGB%2X%02X%02X", r,g,b);
rtn = String::New(szTmp);
}
else
rtn = Undefined();

return rtn;
}

js:
void test_getc_function(Handle<Context> pContext, Handle<ObjectTemplate> pObj)
{
Handle<String> source = String::New("var data = setColor(255,128,0);");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();

Handle<String> js_data = String::New("data");
Handle<Value> js_data_value = pContext->Global()->Get(js_data);

// Convert the result to an ASCII string and print it.
String::AsciiValue ascii(js_data_value);
printf("%s\n", *ascii);
}
>>> RGBFF8000

2.3.2 全局数据

c++:

int x = 0;
Handle<Value> XGetter(Local<String> key,const AccessorInfo& info)
{
return Integer::New(x);
}

void XSetter(Local<String> key, Local<Value> value,const AccessorInfo& info)
{
x = value->Int32Value();
}

js:

void test_getc_data(Handle<Context> pContext, Handle<ObjectTemplate> pObj)
{
Handle<String> source = String::New("var data1 = x; x=200; var data2=x;");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();

{
Handle<String> js_data = String::New("data1");
Handle<Value> js_data_value = pContext->Global()->Get(js_data);
String::AsciiValue ascii(js_data_value);
printf("data1 = %s\n", *ascii);
}

{
Handle<String> js_data = String::New("data2");
Handle<Value> js_data_value = pContext->Global()->Get(js_data);
String::AsciiValue ascii(js_data_value);
printf("data2 = %s\n", *ascii);
}
}
>>> data1 = 0
data2 = 200

2.3.3 类

c++

struct Point
{
Point()
{
x_ = 0;
y_ = 0;
}
Point(int x, int y)
{
x_ = x;
y_ = y;
}

int getX() const {
return x_;
}
int getY() const { return y_; }
void setX(int value) { x_ = value; }
void setY(int value) { y_ = value; }
bool isNull() const { return x_ == 0 && y_ == 0; }
void show()
{
char szTmp[80] = "";
_stprintf(szTmp, "x,y = %d,%d\n", x_, y_);
printf(szTmp);
}
int x_, y_;
};

Handle<Value> GetPointX(Local<String> key,const AccessorInfo &info)
{
Handle<Object> obj = info.This ();
//Local<Object> self = info.Holder(); //使用此种方法会死!!!-
Point& point = *static_cast<Point*> (Local<External>::Cast(obj->GetInternalField(0))->Value ());
int value = point.x_;
return Integer::New(value);
}

void SetPointX(Local<String> key, Local<Value> value,const AccessorInfo& info)
{
Handle<Object> obj = info.This ();
Point& point = *static_cast<Point*> (Local<External>::Cast(obj->GetInternalField(0))->Value ());
point.x_ = value->Int32Value();
}

Handle<Value> GetPointY(Local<String> key,const AccessorInfo &info)
{
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
int value = static_cast<Point*>(ptr)->y_;
return Integer::New(value);
}

void SetPointY(Local<String> key, Local<Value> value,const AccessorInfo& info)
{
Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
static_cast<Point*>(ptr)->y_ = value->Int32Value();
}

Handle<Value> ShowPoint(const Arguments& args)
{
Local<Object> self = args.Holder();
//Local<Object> self = info.Holder();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
static_cast<Point*>(ptr)->show();

return Undefined();
}

js

void test_getc_object(Handle<Context> pContext, Handle<ObjectTemplate> pObj)
{
test_getobject(pContext);return;

// Create a string containing the JavaScript source code.
Handle<String> source = String::New("var pt=new Point(10,20);");

// Compile the source code.
Handle<Script> script = Script::Compile(source);

// Run the script to get the result.
Handle<Value> result = script->Run();

Handle<String> js_data = String::New("pt");
Handle<Value> js_data_value = pContext->Global()->Get(js_data);

// Convert the result to an ASCII string and print it.
{
String::AsciiValue ascii(js_data_value);
printf("pt = %s\n", *ascii);
}

Handle<Object> js_data_object = Handle<Object>::Cast(js_data_value);

Handle<Value> key = String::New("x");
Handle<Value> objX = js_data_object->Get(key);
{
String::AsciiValue ascii(objX);
printf("pt.x = %s\n", *ascii);
}
}
>>> Point = function Point() { [native code] }
Point is function
Point is object
newObj is object
src obj.x = 3
last obj.x = 30
begin newObj.show() : x,y = 30,4
newObj.show() = undefined

3. 教训

在VS200X C++中,请都使用/MDD 编译选项
对于类,需要绑定一个构造函数,主要目的是用来生成C++对象。该对象千万不要使用局部变量,而要是指针
对于C++扩展的类,通过FunctionTemplate来实现;而不要使用ObjectTemplate
对于JS中的全局对象,可以通过ObjectTemplate来实现。实际上就是绑定全局API和变量

基于V8引擎的C++和JS的相互交互的更多相关文章

  1. JS&Swift相互交互

    加载本地HTML文件       x         override func loadView() {    super.loadView()    let conf = WKWebViewCon ...

  2. Google V8 引擎 原理详解

    V8 引擎概览 V8 引擎简介 Google V8 引擎使用 C++ 代码编写,实现了 ECMAScript 规范的第五版,可以运行在所有的主流 操作系统中,甚至可以运行在移动终端 ( 基于 ARM ...

  3. JavaScript深入浅出第4课:V8引擎是如何工作的?

    摘要: 性能彪悍的V8引擎. <JavaScript深入浅出>系列: JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼? JavaScript深入浅出第2课:函数是一等 ...

  4. Node.js和Chrome V8 引擎了解

    说起Node就不得不先介绍一个Chrome V8 引擎. 随着Web相关技术的发展,JavaScript所要承担的工作也越来越多,早就超越了“表单验证”的范畴,这就更需要快速的解析和执行JavaScr ...

  5. 深入浏览器工作原理和JS引擎(V8引擎为例)

    浏览器工作原理和JS引擎 1.浏览器工作原理 在浏览器中输入查找内容,浏览器是怎样将页面加载出来的?以及JavaScript代码在浏览器中是如何被执行的? 大概流程可观察以下图: 首先,用户在浏览器搜 ...

  6. 探究JS V8引擎下的“数组”底层实现

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/np9Yoo02pEv9n_LCusZn3Q作者:李超 JavaScript 中的数组有很多特性 ...

  7. 初识NodeJS,一个基于GoogleV8引擎的Javascript运行环境

    思考 首先我们来思考一个问题:我们都知道几乎所有现代主流浏览器都全面支持了ECMAScript 5.1版标准,而JavaScript的标准是ECMAScript.那么我们就容易认为JavaScript ...

  8. 深入出不来nodejs源码-V8引擎初探

    原本打算是把node源码看得差不多了再去深入V8的,但是这两者基本上没办法分开讲. 与express是基于node的封装不同,node是基于V8的一个应用,源码内容已经渗透到V8层面,因此这章简述一下 ...

  9. Javascript的V8引擎研究

    1.针对上下文的Snapshot技术 什么是上下文(Contexts)?实际是JS应用程序的运行环境,避免应用程序的修改相互影响,例如一个页面js修改内置对象方法toString,不应该影响到另外页面 ...

随机推荐

  1. css切角效果,折角效果

    html <div class="one">12345</div> <div class="two">abcde</d ...

  2. WXSS学习

    <view class='container'> <button type='default'>测试</button> <button type='defau ...

  3. day01 mysql认识 安装 配置 起服务 密码 字符集 用户授权

    day01 mysql      一.认识mysql     关系型数据库:         最流行的关系型数据库管理系统,支持大型数据库,处理上千万条记录         关系型: oracle,  ...

  4. VMWare 禁用虚拟内存文件(*.vmem)

    1.使用 VMWare 虚拟机,虚拟机启动后,会在虚拟机目录下建立一个与虚拟内存大小相同的 .vmem文件,例如:564db13c-c92d-3d3a-41a0-f62af7536fda.vmem. ...

  5. PHP - 实现 strStr()

    实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在,则返 ...

  6. 36. 解决线程问题方式一(同步代码块synchronized)

    解决线程问题: 方式一:同步代码块(synchronized) 语法: synchronized ("锁对象") {             //需要锁定的代码       }   ...

  7. 34. Thread类的常用方法

    1.构造方法 Thread() 分配新的 Thread 对象. Thread(String name)  分配新的 Thread 对象并指定线程名字 2.方法 1)setName(String nam ...

  8. NX二次开发-UFUN输入对象tag获得part名字UF_OBJ_ask_owning_part

    NX11+VS2013 #include <uf.h> #include <uf_modl.h> #include <uf_part.h> #include < ...

  9. fastText一个库用于词表示的高效学习和句子分类

    fastText fastText 是 Facebook 开发的一个用于高效学习单词呈现以及语句分类的开源库. 要求 fastText 使用 C++11 特性,因此需要一个对 C++11 支持良好的编 ...

  10. detours3.0文档翻译

    拦截二进制函数 Detours库可以在运行过程中动态拦截函数调用.detours将目标函数前几个指令替换为一个无条件跳转,跳转到用户定义的detour函数.被拦截的函数保存在trampoline函数中 ...