<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[刘新修]]></title> 
<link>http://pic1.liuxinxiu.com:80/index.php</link> 
<description><![CDATA[刘新修的个人博客 (Liuxinxiu'S Blog)]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[刘新修]]></copyright>
<item>
<link>http://pic1.liuxinxiu.com:80/V8/</link>
<title><![CDATA[使用 Google V8 引擎开发可定制的应用程序]]></title> 
<author>刘新修 &lt;admin@yourname.com&gt;</author>
<category><![CDATA[NodeJs平台]]></category>
<pubDate>Thu, 02 Mar 2017 02:20:49 +0000</pubDate> 
<guid>http://pic1.liuxinxiu.com:80/V8/</guid> 
<description>
<![CDATA[ 
	<p>&nbsp;V8 引擎概览</p><div>&nbsp;</div><div>Google V8 引擎使用 C++ 代码编写，实现了 ECMAScript 规范的第五版，可以运行在所有的主流</div><div>&nbsp;</div><div>操作系统中，甚至可以运行在移动终端 ( 基于 ARM 的处理器，如 HTC G7 等 )。V8 最早被开发用以嵌入到 Google 的开源浏览器 Chrome 中，但是 V8 是一个可以独立的模块，完全可以嵌入您自己的应用，著名的 Node.js( 一个异步的服务器框架，可以在服务端使用 JavaScript 写出搞笑的网络服务器 ) 就是基于 V8 引擎的。</div><div>&nbsp;</div><div>和其他 JavaScript 引擎一样，V8 会编译 / 执行 JavaScript 代码，管理内存，负责垃圾回收，与宿主语言的交互等。V8 的垃圾回收器采用了众多技术，使得其运行效率大大提高。通过暴露宿主对象 ( 变量，函数等 ) 到 JavaScript，JavaScript 可以访问宿主环境中的对象，并在脚本中完成对宿主对象的操作。</div><div>&nbsp;</div><div>V8 引擎基本概念</div><div>&nbsp;</div><div>图 1. V8 引擎基本概念关系图 ( 根据 Google V8 官方文档 )&nbsp;</div><div><a href="http://at.liuxinxiu.com/2017/03/image/001.jpg" target="_blank"><img src="http://at.liuxinxiu.com/2017/03/image/001.jpg" width="425" height="267" alt="" /></a></div><div><div>handle</div><div>&nbsp;</div><div>handle 是指向对象的指针，在 V8 中，所有的对象都通过 handle 来引用，handle 主要用于 V8 的垃圾回收机制。</div><div>&nbsp;</div><div>在 V8 中，handle 分为两种：持久化 (Persistent)handle 和本地 (Local)handle，持久化 handle 存放在堆上，而本地 handle 存放在栈上。这个与 C/C++ 中的堆和栈的意义相同 ( 简而言之，堆上的空间需要开发人员自己申请，使用完成之后显式的释放；而栈上的为自动变量，在退出函数 / 方法之后自动被释放 )。持久化 handle 与本地 handle 都是 Handle 的子类。在 V8 中，所有数据访问均需要通过 handle。需要注意的是，使用持久化 handle 之后，需要显式的调用 Dispose() 来通知垃圾回收机制。</div><div>&nbsp;</div><div>作用域 (scope)</div><div>&nbsp;</div><div>scope 是 handle 的集合，可以包含若干个 handle，这样就无需将每个 handle 逐次释放，而是直接释放整个 scope。</div><div>&nbsp;</div><div>在使用本地 handle 时，需要声明一个 HandleScope 的实例，scope 是 handle 的容器，使用 scope，则无需依次释放 handle。</div><div>&nbsp;</div><div>&nbsp;HandleScope handle_scope;&nbsp;</div><div>&nbsp;Local&lt;ObjectTemplate&gt; temp;&nbsp;</div><div>&nbsp;</div><div>上下文 (context)</div><div>&nbsp;</div><div>context 是一个执行器环境，使用 context 可以将相互分离的 JavaScript 脚本在同一个 V8 实例中运行，而互不干涉。在运行 JavaScript 脚本是，需要显式的指定 context 对象。</div><div>&nbsp;</div><div>数据及模板</div><div>&nbsp;</div><div>由于 C++ 原生数据类型与 JavaScript 中数据类型有很大差异，因此 V8 提供了 Data 类，从 JavaScript 到 C++，从 C++ 到 JavaScrpt 都会用到这个类及其子类，比如：</div><div>&nbsp;</div><div>&nbsp;Handle&lt;Value&gt; Add(const Arguments&amp; args)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> int a = args[0]-&gt;Uint32Value();&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> int b = args[1]-&gt;Uint32Value();&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return Integer::New(a+b);&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>Integer 即为 Data 的一个子类。</div><div>&nbsp;</div><div>V8 中，有两个模板 (Template) 类 ( 并非 C++ 中的模板类 )：对象模板 (ObjectTempalte) 和函数模板 (FunctionTemplate)，这两个模板类用以定义 JavaScript 对象和 JavaScript 函数。我们在后续的小节部分将会接触到模板类的实例。通过使用 ObjectTemplate，可以将 C++ 中的对象暴露给脚本环境，类似的，FunctionTemplate 用以将 C++ 函数暴露给脚本环境，以供脚本使用。</div><div>&nbsp;</div><div>初始化 context 是使用 V8 引擎所必需的过程，代码非常简单：</div><div>&nbsp;</div><div>&nbsp;Persistent&lt;Context&gt; context = Context::New();&nbsp;</div><div>V8 引擎使用示例</div><div>&nbsp;</div><div>有了上面所述的基本概念之后，我们来看一下一个使用 V8 引擎的应用程序的基本流程：</div><div>&nbsp;</div><div>创建 HandleScope 实例</div><div>创建一个持久化的 Context</div><div>进入 Context</div><div>创建脚本字符串</div><div>创建 Script 对象，通过 Script::Compile()</div><div>执行脚本对象的 Run 方法</div><div>获取 / 处理结果</div><div>显式的调用 Context 的 Dispose 方法</div><div>基本代码模板</div><div>&nbsp;</div><div>&nbsp;</div><div>清单 1. 代码模块&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div>&nbsp;#include &lt;v8.h&gt;&nbsp;</div><div>&nbsp;</div><div>&nbsp;using namespace v8;&nbsp;</div><div>&nbsp;</div><div>&nbsp;int main(int argc, char *argv[]) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // 创建一个句柄作用域 ( 在栈上 )&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> HandleScope handle_scope;&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // 创建一个新的上下文对象</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Persistent&lt;Context&gt; context = Context::New();&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // 进入上一步创建的上下文，用于编译执行 helloworld&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Context::Scope context_scope(context);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // 创建一个字符串对象，值为'Hello, Wrold!', 字符串对象被 JS 引擎</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // 求值后，结果为'Hello, World!'</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Handle&lt;String&gt; source = String::New(&quot;'Hello' + ', World!'&quot;);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // 编译字符串对象为脚本对象</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Handle&lt;Script&gt; script = Script::Compile(source);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // 执行脚本，获取结果</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Handle &lt;Value&gt; result = script-&gt;Run();&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // 释放上下文资源</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> context.Dispose();&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // 转换结果为字符串</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> String::AsciiValue ascii(result);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> printf(&quot;%s&#92;n&quot;, *ascii);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return 0;&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>以上代码为一个使用 V8 引擎来运行脚本的基本模板，可以看到，开发人员可以很容易的在自己的代码中嵌入 V8 来处理 JavaScript 脚本。我们在下面小节中详细讨论如何在脚本中访问 C++ 资源。</div><div>&nbsp;</div><div>使用 C++ 变量</div><div>&nbsp;</div><div>在 JavaScript 与 V8 间共享变量事实上是非常容易的，基本模板如下：</div><div>&nbsp;</div><div>&nbsp;</div><div>清单 2. 共享变量&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div>&nbsp;static type xxx;&nbsp;</div><div>&nbsp;</div><div>&nbsp;static Handle&lt;Value&gt; xxxGetter(&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Local&lt;String&gt; name,&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> const AccessorInfo&amp; info)&#123;&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> //code about get xxx&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>&nbsp;static void xxxSetter(&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Local&lt;String&gt; name,&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Local&lt;Value&gt; value,&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> const AccessorInfo&amp; info)&#123;&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> //code about set xxx&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>首先在 C++ 中定义数据，并以约定的方式定义 getter/setter 函数，然后需要将 getter/setter 通过下列机制公开给脚本：</div><div>&nbsp;</div><div>&nbsp;global-&gt;SetAccessor(String::New(&quot;xxx&quot;), xxxGetter, xxxSetter);&nbsp;</div><div>&nbsp;</div><div>其中，global 对象为一个全局对象的模板：</div><div>&nbsp;</div><div>&nbsp;Handle&lt;ObjectTemplate&gt; global = ObjectTemplate::New();&nbsp;</div><div>&nbsp;</div><div>下面我们来看一个实例：</div><div>&nbsp;</div><div>&nbsp;</div><div>清单 3. 实例 1&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div>&nbsp;static char sname[512] = &#123;0&#125;;&nbsp;</div><div>&nbsp;</div><div>&nbsp;static Handle&lt;Value&gt; NameGetter(Local&lt;String&gt; name,&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> const AccessorInfo&amp; info) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return String::New((char*)&amp;sname,strlen((char*)&amp;sname));&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>&nbsp;static void NameSetter(Local&lt;String&gt; name,&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> Local&lt;Value&gt; value,&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> const AccessorInfo&amp; info) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Local&lt;String&gt; str = value-&gt;ToString();&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> str-&gt;WriteAscii((char*)&amp;sname);&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>定义了 NameGetter, NameSetter 之后，在 main 函数中，将其注册在 global 上：</div><div>&nbsp;</div><div>&nbsp;// Create a template for the global object.&nbsp;</div><div>&nbsp;Handle&lt;ObjectTemplate&gt; global = ObjectTemplate::New();&nbsp;</div><div>&nbsp;</div><div>&nbsp;//public the name variable to script&nbsp;</div><div>&nbsp;global-&gt;SetAccessor(String::New(&quot;name&quot;), NameGetter, NameSetter);&nbsp;</div><div>&nbsp;</div><div>在 C++ 中，将 sname 的值设置为&rdquo;cpp&rdquo;：</div><div>&nbsp;</div><div>&nbsp;//set sname to &quot;cpp&quot; in cpp program&nbsp;</div><div>&nbsp;strncpy(sname, &quot;cpp&quot;, sizeof(sname));&nbsp;</div><div>&nbsp;</div><div>然后在 JavaScript 中访问该变量，并修改：</div><div>&nbsp;</div><div>&nbsp;print(name);&nbsp;</div><div>&nbsp;</div><div>&nbsp;//set the variable `name` to &quot;js&quot;</div><div>&nbsp;name='js';&nbsp;</div><div>&nbsp;print(name);&nbsp;</div><div>&nbsp;</div><div>运行结果如下：</div><div>&nbsp;</div><div>&nbsp;cpp&nbsp;</div><div>&nbsp;js&nbsp;</div><div>&nbsp;</div><div>运行脚本，第一个 print 调用会打印在 C++ 代码中设置的 name 变量的值：cpp，然后我们在脚本中修改 name 值为：js，再次调用 print 函数则打印出设置后的值：js。</div><div>&nbsp;</div><div>调用 C++ 函数</div><div>&nbsp;</div><div>在 JavaScript 中调用 C++ 函数是脚本化最常见的方式，通过使用 C++ 函数，可以极大程度的增强 JavaScript 脚本的能力，如文件读写，网络 / 数据库访问，图形 / 图像处理等等，而在 V8 中，调用 C++ 函数也非常的方便。</div><div>&nbsp;</div><div>在 C++ 代码中，定义以下原型的函数：</div><div>&nbsp;</div><div>&nbsp;Handle&lt;Value&gt; function(constArguments&amp; args)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> //return something&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>然后，再将其公开给脚本：</div><div>&nbsp;</div><div>&nbsp;global-&gt;Set(String::New(&quot;function&quot;),FunctionTemplate::New(function));&nbsp;</div><div>&nbsp;</div><div>同样，我们来看两个示例：</div><div>&nbsp;</div><div>&nbsp;</div><div>清单 4. 实例 2&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div>&nbsp;Handle&lt;Value&gt; Add(const Arguments&amp; args)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> int a = args[0]-&gt;Uint32Value();&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> int b = args[1]-&gt;Uint32Value();&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return Integer::New(a+b);&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>&nbsp;Handle&lt;Value&gt; Print(const Arguments&amp; args) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> bool first = true;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> for (int i = 0; i &lt; args.Length(); i++) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> HandleScope handle_scope;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> if (first) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> first = false;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> &#125; else &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> printf(&quot; &quot;);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> &#125;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> String::Utf8Value str(args[i]);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> const char* cstr = ToCString(str);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> printf(&quot;%s&quot;, cstr);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> printf(&quot;&#92;n&quot;);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> fflush(stdout);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return Undefined();&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>函数 Add 将两个参数相加，并返回和。函数 Print 接受任意多个参数，然后将参数转换为字符串输出，最后输出换行。</div><div>&nbsp;</div><div>&nbsp;global-&gt;Set(String::New(&quot;print&quot;), FunctionTemplate::New(Print));&nbsp;</div><div>&nbsp;global-&gt;Set(String::New(&quot;add&quot;), FunctionTemplate::New(Add));&nbsp;</div><div>&nbsp;</div><div>我们定义以下脚本：</div><div>&nbsp;</div><div>&nbsp;var x = (function(a, b)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return a + b; <span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span></div><div>&nbsp;&#125;)(12, 7);&nbsp;</div><div>&nbsp;</div><div>&nbsp;print(x);&nbsp;</div><div>&nbsp;</div><div>&nbsp;//invoke function add defined in cpp&nbsp;</div><div>&nbsp;var y = add(43, 9);&nbsp;</div><div>&nbsp;print(y);&nbsp;</div><div>&nbsp;</div><div>运行结果如下：</div><div>&nbsp;</div><div>&nbsp;19&nbsp;</div><div>&nbsp;52&nbsp;</div><div>&nbsp;</div><div>使用 C++ 类</div><div>&nbsp;</div><div>如果从面向对象的视角来分析，最合理的方式是将 C++ 类公开给 JavaScript，这样可以将 JavaScript 内置的对象数量大大增加，从而尽可能少的使用宿主语言，而更大的利用动态语言的灵活性和扩展性。事实上，C++ 语言概念众多，内容繁复，学习曲线较 JavaScript 远为陡峭。最好的应用场景是：既有脚本语言的灵活性，又有 C/C++ 等系统语言的效率。使用 V8 引擎，可以很方便的将 C++ 类&rdquo;包装&rdquo;成可供 JavaScript 使用的资源。</div><div>&nbsp;</div><div>我们这里举一个较为简单的例子，定义一个 Person 类，然后将这个类包装并暴露给 JavaScript 脚本，在脚本中新建 Person 类的对象，使用 Person 对象的方法。</div><div>&nbsp;</div><div>首先，我们在 C++ 中定义好类 Person：</div><div>&nbsp;</div><div>&nbsp;</div><div>清单 5. 定义类&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div>&nbsp;class Person &#123;&nbsp;</div><div>&nbsp;private:&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> unsigned int age;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> char name[512];&nbsp;</div><div>&nbsp;</div><div>&nbsp;public:&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Person(unsigned int age, char *name) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> this-&gt;age = age;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> strncpy(this-&gt;name, name, sizeof(this-&gt;name));&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> unsigned int getAge() &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> return this-&gt;age;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> void setAge(unsigned int nage) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> this-&gt;age = nage;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> char *getName() &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> return this-&gt;name;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> void setName(char *nname) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> strncpy(this-&gt;name, nname, sizeof(this-&gt;name));&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div>&nbsp;&#125;;&nbsp;</div><div>&nbsp;</div><div>Person 类的结构很简单，只包含两个字段 age 和 name，并定义了各自的 getter/setter. 然后我们来定义构造器的包装：</div><div>&nbsp;</div><div>&nbsp;Handle&lt;Value&gt; PersonConstructor(const Arguments&amp; args)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Handle&lt;Object&gt; object = args.This();&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> HandleScope handle_scope;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> int age = args[0]-&gt;Uint32Value();&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> String::Utf8Value str(args[1]);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> char* name = ToCString(str);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Person *person = new Person(age, name);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> object-&gt;SetInternalField(0, External::New(person));&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return object;&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>从函数原型上可以看出，构造器的包装与上一小节中，函数的包装是一致的，因为构造函数在 V8 看来，也是一个函数。需要注意的是，从 args 中获取参数并转换为合适的类型之后，我们根据此参数来调用 Person 类实际的构造函数，并将其设置在 object 的内部字段中。紧接着，我们需要包装 Person 类的 getter/setter：</div><div>&nbsp;</div><div>&nbsp;Handle&lt;Value&gt; PersonGetAge(const Arguments&amp; args)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Local&lt;Object&gt; self = args.Holder();&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Local&lt;External&gt; wrap = Local&lt;External&gt;::Cast(self-&gt;GetInternalField(0));&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> void *ptr = wrap-&gt;Value();&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return Integer::New(static_cast&lt;Person*&gt;(ptr)-&gt;getAge());&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>&nbsp;Handle&lt;Value&gt; PersonSetAge(const Arguments&amp; args)&nbsp;</div><div>&nbsp;&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Local&lt;Object&gt; self = args.Holder();&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Local&lt;External&gt; wrap = Local&lt;External&gt;::Cast(self-&gt;GetInternalField(0));&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> void* ptr = wrap-&gt;Value();&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> static_cast&lt;Person*&gt;(ptr)-&gt;setAge(args[0]-&gt;Uint32Value());&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return Undefined();&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>而 getName 和 setName 的与上例类似。在对函数包装完成之后，需要将 Person 类暴露给脚本环境：</div><div>&nbsp;</div><div>首先，创建一个新的函数模板，将其与字符串&rdquo;Person&rdquo;绑定，并放入 global：</div><div>&nbsp;</div><div>&nbsp;Handle&lt;FunctionTemplate&gt; person_template = FunctionTemplate::New(PersonConstructor);&nbsp;</div><div>&nbsp;person_template-&gt;SetClassName(String::New(&quot;Person&quot;));&nbsp;</div><div>&nbsp;global-&gt;Set(String::New(&quot;Person&quot;), person_template);&nbsp;</div><div>&nbsp;</div><div>然后定义原型模板：</div><div>&nbsp;</div><div>&nbsp;Handle&lt;ObjectTemplate&gt; person_proto = person_template-&gt;PrototypeTemplate();&nbsp;</div><div>&nbsp;</div><div>&nbsp;person_proto-&gt;Set(&quot;getAge&quot;, FunctionTemplate::New(PersonGetAge));&nbsp;</div><div>&nbsp;person_proto-&gt;Set(&quot;setAge&quot;, FunctionTemplate::New(PersonSetAge));&nbsp;</div><div>&nbsp;</div><div>&nbsp;person_proto-&gt;Set(&quot;getName&quot;, FunctionTemplate::New(PersonGetName));&nbsp;</div><div>&nbsp;person_proto-&gt;Set(&quot;setName&quot;, FunctionTemplate::New(PersonSetName));&nbsp;</div><div>&nbsp;</div><div>最后设置实例模板：</div><div>&nbsp;</div><div>&nbsp;Handle&lt;ObjectTemplate&gt; person_inst = person_template-&gt;InstanceTemplate();&nbsp;</div><div>&nbsp;person_inst-&gt;SetInternalFieldCount(1);&nbsp;</div><div>&nbsp;</div><div>随后，创建一个用以测试的脚本：</div><div>&nbsp;</div><div>&nbsp;//global function to print out detail info of person&nbsp;</div><div>&nbsp;function printPerson(person)&#123;&nbsp;</div><div>&nbsp; &nbsp; print(person.getAge()+&quot;:&quot;+person.getName());&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>&nbsp;//new a person object&nbsp;</div><div>&nbsp;var person = new Person(26, &quot;juntao&quot;);&nbsp;</div><div>&nbsp;</div><div>&nbsp;//print it out&nbsp;</div><div>&nbsp;printPerson(person);&nbsp;</div><div>&nbsp;</div><div>&nbsp;//set new value&nbsp;</div><div>&nbsp;person.setAge(28);&nbsp;</div><div>&nbsp;person.setName(&quot;juntao.qiu&quot;);&nbsp;</div><div>&nbsp;</div><div>&nbsp;//print it out&nbsp;</div><div>&nbsp;printPerson(person);&nbsp;</div><div>&nbsp;</div><div>运行得到以下结果：</div><div>&nbsp;</div><div>&nbsp;26:juntao&nbsp;</div><div>&nbsp;28:juntao.qiu&nbsp;</div><div>简单示例</div><div>&nbsp;</div><div>在这一小节中，我们将编写一个简单的桌面计算器：表达式求值部分通过 V8 引擎来进行，而流程控制部分则放在 C++ 代码中，这样可以将表达式解析等复杂细节绕开。同时，我们还得到了一个额外的好处，用户在脚本中可以自定义函数，从而可以在计算器中定义自己的运算规则。</div><div>&nbsp;</div><div>桌上计算器</div><div>&nbsp;</div><div>计算器程序首先进入一个 MainLoop，从标准输入读取一行命令，然后调用 V8 引擎去求值，然后将结果打印到控制台，然后再进入循环：</div><div>&nbsp;</div><div>&nbsp;</div><div>清单 6. 桌面计算器示例&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div>&nbsp;void MainLoop(Handle&lt;Context&gt; context) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> while(true) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> char buffer[1024] = &#123;0&#125;;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> printf(&quot;$ &quot;);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> char *str = fgets(buffer, sizeof(buffer), stdin);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> if(str == NULL) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> break;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> &#125;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> HandleScope handle_scope;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> ExecuteString(String::New(str), String::New(&quot;calc&quot;), true);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>在 main 函数中设置全局对象，创建上下文对象，并进入 MainLoop：</div><div>&nbsp;</div><div>&nbsp;int main(int argc, char *argv[])&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> HandleScope handle_scope;&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // Create a template for the global object.&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Handle&lt;ObjectTemplate&gt; global = ObjectTemplate::New();&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // Expose the local functions to script&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> global-&gt;Set(String::New(&quot;load&quot;), FunctionTemplate::New(Load));&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> global-&gt;Set(String::New(&quot;print&quot;), FunctionTemplate::New(Print));&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> global-&gt;Set(String::New(&quot;quit&quot;), FunctionTemplate::New(Quit));&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // Create a new execution environment containing the built-in&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // functions&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Handle&lt;Context&gt; context = Context::New(NULL, global);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // Enter the newly created execution environment.&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Context::Scope context_scope(context);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> // Enter main loop&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> MainLoop(context);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> V8::Dispose();&nbsp;</div><div>&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return 0;&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>在 main 函数中，为脚本提供了三个函数，load 函数用以将用户指定的脚本加载进来，并放入全局的上下文中一边引用，print 函数用以打印结果，而 quit 提供用户退出计算器的功能。</div><div>&nbsp;</div><div>测试一下：</div><div>&nbsp;</div><div>&nbsp;$ 1+2&nbsp;</div><div>&nbsp;3&nbsp;</div><div>&nbsp;</div><div>&nbsp;$ (10+3)/(9.0-5)&nbsp;</div><div>&nbsp;3.25&nbsp;</div><div>&nbsp;</div><div>&nbsp;$ typeof print&nbsp;</div><div>&nbsp;function&nbsp;</div><div>&nbsp;</div><div>&nbsp;$ typeof non&nbsp;</div><div>&nbsp;undefined&nbsp;</div><div>&nbsp;</div><div>&nbsp;// 自定义函数</div><div>&nbsp;$ function add(a, b)&#123;return a+b;&#125;&nbsp;</div><div>&nbsp;$ add(999, 2323)&nbsp;</div><div>&nbsp;3322&nbsp;</div><div>&nbsp;</div><div>&nbsp;// 查看 print 标识符的内容</div><div>&nbsp;$ print&nbsp;</div><div>&nbsp;function print() &#123; [native code] &#125;&nbsp;</div><div>&nbsp;</div><div>load 函数提供了用户自定义函数的功能，将脚本文件作为一个字符串加载到内存，然后对该字符串编译，求值，并将处理过的脚本对象放入当前 context 中，以便用户使用。</div><div>&nbsp;</div><div>&nbsp;Handle&lt;Value&gt; Load(const Arguments&amp; args)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> if(args.Length() != 1)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> return Undefined();&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> HandleScope handle_scope;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> String::Utf8Value file(args[0]);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Handle&lt;String&gt; source = ReadFile(*file);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> ExecuteString(source, String::New(*file), false);&nbsp;</div><div>&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return Undefined();&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>而 ExecuteString 函数，负责将字符串编译运行：</div><div>&nbsp;</div><div>&nbsp;bool ExecuteString(Handle&lt;String&gt; source,&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> &nbsp; Handle&lt;Value&gt; name,&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> &nbsp; bool print_result)&nbsp;</div><div>&nbsp;&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> HandleScope handle_scope;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> TryCatch try_catch;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> Handle&lt;Script&gt; script = Script::Compile(source, name);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> if (script.IsEmpty()) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> return false;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125; else &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> Handle&lt;Value&gt; result = script-&gt;Run();&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> if (result.IsEmpty()) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> return false;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> &#125; else &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> if (print_result &amp;&amp; !result-&gt;IsUndefined()) &#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> String::Utf8Value str(result);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> const char* cstr = ToCString(str);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> printf(&quot;%s&#92;n&quot;, cstr);&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> &#125;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> return true;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> &#125;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>将下列内容存入一个文本文件，并命令为 calc.js：</div><div>&nbsp;</div><div>&nbsp;function sum()&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> var s = 0;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> for(var i = 0; i &lt; arguments.length; i++)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> s += arguments[i];&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return s;&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>&nbsp;function avg()&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> var args = arguments;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> var count = args.length;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> var sum = 0;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> for(var i = 0; i &lt; count; i++)&#123;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;&nbsp;&nbsp;</span> sum += args[i];&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> &#125;&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">&nbsp;&nbsp;</span> return sum/count;&nbsp;</div><div>&nbsp;&#125;&nbsp;</div><div>&nbsp;</div><div>然后在计算器中测试：</div><div>&nbsp;</div><div>&nbsp;// 此时 sum 符号位定义</div><div>&nbsp;$ typeof sum&nbsp;</div><div>&nbsp;undefined&nbsp;</div><div>&nbsp;</div><div>&nbsp;// 加载文件，并求值</div><div>&nbsp;$ load(&quot;calc.js&quot;)&nbsp;</div><div>&nbsp;</div><div>&nbsp;// 可以看到，sum 的类型为函数</div><div>&nbsp;$ typeof sum&nbsp;</div><div>&nbsp;function&nbsp;</div><div>&nbsp;</div><div>&nbsp;$ sum(1,2,3,4,5,6,7,8,9)&nbsp;</div><div>&nbsp;45&nbsp;</div><div>结束语</div><div>&nbsp;</div><div>使用 V8 引擎，可以轻松的将脚本的好处带进 C++ 应用，使得 C++ 应用更具灵活性，扩展性。我们在文中讨论了基本的模板，如何使用 C++ 变量，函数，以及类。最后的实例中给出了一个计算器的原型。由于 V8 的设计原则，开发人员可以快速的将其嵌入到自己的应用中，并且无需太过担心脚本语言的执行效率。</div></div>
]]>
</description>
</item><item>
<link>http://pic1.liuxinxiu.com:80/V8/#blogcomment</link>
<title><![CDATA[[评论] 使用 Google V8 引擎开发可定制的应用程序]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://pic1.liuxinxiu.com:80/V8/#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>