博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 掌握V8的架构和使用过程


V8内部架构相当复杂,但是使用还是很方便的,因为V8把所有功能实现封装到内部的命名空间中,只给使用者提供了相当简洁的外部封装类,这些类都在一个叫做v8的命名空间中,全局函数封装在V8命名空间中(注意大小写有别)。V8引擎使用上的便捷性体现在多个方面:

l  大量采用模板类,统一了所有脚本对象的内存管理和垃圾回收。

l  所有脚本对象不允许直接在堆或栈上构造,这通过私有的构造函数体现出来。对象的创建都使用静态的New方法,对象的类型转换都使用CAST方法。

l  所有对象通过Handle<>模板类的封装来自动管理对象的生命周期,Handle分成LocalPersistent两种。Local在内部栈上管理对象,一旦离开栈作用范围(Scope),这些对象被自动释放。Persistent管理所有永久对象,对象被自动加上引用计数,一旦引用计数为0,永久对象将被放入垃圾回收队列,在合适的时候被系统自动回收。

l  提供了足够使用的回调函数机制来控制V8的运行,通过设置对象模板的访问函数和拦截函数来使用自定义功能。

l  不需要特殊的初始化和反初始化过程,一个集成了V8库的进程可以在任何时机直接使用脚本引擎。

l  脚本执行都需要特定的上下文,每个上下文相当于一个独立的脚本环境。可以随时从一个上下文转移到另一个上下文,也能随时从其它上下文返回到当前上下文。

 

使用V8执行脚本代码最基本的过程:

1.       创建一个上下文对象(Context)

2.       可选设置上下文对应的全局永久对象

3.       通过函数模板创建函数原型、函数对象或者对象模板

4.       通过对象模板创建对象实例

5.       编译脚本代码后执行

 

实际上上述几个步骤中不是每个都必须。如果执行的脚本代码中全部使用了V8的内部对象和函数,没有使用外部自定义对象,那么只需要15两个步骤就够了。中间步骤实际上是为了在脚本环境中创建自定义的类、函数或者对象。

 

不使用自定义对象的例子:

 

使用自定义对象不再提供例子,可以上http://code.google.com/intl/zh-CN/apis/v8/embed.html 站点或者Google开源网站直接查看V8嵌入的例子和应用示例,这不是本文的重点。

在我实现的引擎中,必须把微软脚本引擎规范与V8的功能一一对应,主要涉及到的对应有:

1.       每个引擎组件实例需要对应一个Context实例

2.       每个命名项需要对应一个Context实例

3.       脚本引擎中的Global对象和每个命名项对象各自对应Context的全局对象

4.       脚本代码中产生的COM对象必须创建一个永久Object对象并缓存

5.       所有COM对象的属性和方法必须添加对应的访问回调函数和拦截回调函数

6.       V8中创建的事件回调函数必须创建一个对应的COM对象反馈给客户端

7.       函数调用的每个参数和返回值必须与VARIANT类型相互转换

8.       Jscript特有的对象和函数必须添加到新创建的每个Context

9.       V8中的索引化访问(如a[2] = ‘abc’;)必须转换成COM中的枚举器访问或者属性化访问

10.   所有脚本运行中间产生的COM对象与V8永久对象的映射关系必须缓存,当V8永久对象被回收时自动释放缓存的COM对象