您的位置:首页 > 其它

V8 引擎使用心得

2010-09-29 19:17 393 查看
在公司一直负责一个界面引擎的模块的设计开发工作,主要使用XML和JavaScript两种技术。

最初我们使用的是MS的JS引擎(由IActiveScript及一些相关接口组成,下称MS-JS),后来由于一些问题,将MS-JS替换成Google才推出不久的JS引擎V8(下称V8-JS)。
MS-JS不知道多久没更新了,不过也还好用,文档写得也清楚。
V8-JS是Google的Chrome浏览器中的一个亮点,刚推出不久,还在不断更新中,性能据说比MS的高过不止一个数量级,还有很重要的一点是它开源,“源码之前,了无秘密”,不过要揭示这里面的秘密,也是要精通不少技术的,比如汇编语言、编译原理、C++模板、设计模式等等,这也难怪,毕竟这是个虚拟机嘛。本人所知也是略知皮毛,在项目中有了一些使用经验,和大家分享一下。
两者设计理念上有一些差异。MS-JS以COM接口的形式发布,引擎建立在IDispatch接口的基础之上,虽然效率上要吃些亏,但是实现了在二进制代码级别上的重用,以至于我们能到处看到MS-JS的身影,在IE浏览器中,在Windows Script Host中等等。我们还可以在各种不同的编程语言中使用它(COM的确是软件重用的一个成功典范)。V8-JS以C++库的形式发布,大概是因为V8-JS对性能的要求很高,而且主要在Chrome中的使用的缘故吧。
作为Javascript的运行环境,两者在使用方式大体上是相同的:宿主程序把自己的对象与JS对象绑定,解释Js脚本并执行,脚本代码在被执行的过程中访问对象的属性和方法,当宿主程序有事件发生时可调用脚本中相应的处理代码。在细节上两者的差别就比较大了,下面分别做些简短的讲述:
1.创建JS引擎(执行上下文)
MS-JS:
//用COM函数CoCreateInstance创建引擎对象
CComPtr<IActiveScript> activeScript;
//创建脚本运行环境
HRESULT hr = ::CoCreateInstance(CLSID_J***AScript, NULL, CLSCTX_INPROC, IID_IActiveScript, (void**)&activeScript);
//创建宿主对象,应用程序需实现IActiveScriptSite,通过IActiveScript的接口函数SetScriptSite与之关联,在第一次执
//行脚本的时候,引擎会向宿主接口查询名字对象的接口。
CComPtr<IActiveScriptSite> pSite = GetScriptSite();//需实现
hr = activeScript->SetScriptSite(pSite);
//添加全局名字对象
AddNameItemToSrcipt(activeScript);//需实现
V8-JS:
//创建v8执行上下文
jsContext = Context::New();
//获得全局对象
Handle<Object> global = jsContext->Global();
//添加名字对象
AddObjectToSrcipt(global);
2.加载脚本
MS-JS:
//获取解析器
CComPtr<IActiveScriptParse> srciptParser;
hr = m_pActiveScript->QueryInterface(IID_IActiveScriptParse, (void**)&srciptParser);
//初始化脚本解析器
hr = srciptParser->InitNew();
//解析脚本
hr = srciptParser->ParseScriptText(bstrScript, NULL, NULL,
NULL, 0, 0, SCRIPTTEXT_ISVISIBLE, NULL, NULL);
V8-JS:
//设置当前运行上下文
Context::Scope contextScope(jsContext);
//捕获异常
TryCatch tryCatch;
//编译脚本
Handle<String> scriptString = CStringToString(bstrScript);
Handle<String> scriptFileName = CStringToString(bstrScriptName);
Handle<Script> script = Script::Compile(scriptString, scriptFileName);
3.运行脚本
MS-JS:
//设置脚本引擎为SCRIPTSTATE_CONNECTED
hr = pActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);
V8-JS:
//设置当前运行上下文
Context::Scope contextScope(jsContext);
//运行
script->Run();
4.调用脚本函数
MS-JS:
//获得全局对象
CComPtr<IDispatch> dispGlobal;
hr = m_pActiveScript->GetScriptDispatch(NULL, &dispGlobal);
//查询函数
DISPID funcID = -1;
OLECHAR *rgszNames[] = {bstrFuncName};
hr = dispGlobal->GetIDsOfNames(IID_NULL, rgszNames, 1, 0, &funcID);
//调用函数
DISPPARAMS dispParams = {NULL, 0, 0, 0};//准备参数列表
hr = dispGlobal->Invoke(funcID, IID_NULL, 0, DISPATCH_METHOD, pDispParams, pVarResult, NULL, NULL);
V8-JS:
//设置当前上下文
Context::Scope contextScope(jsContext);
//捕获异常
TryCatch tryCatch;
//获得函数对象
Handle<Object> global = m_jsContext->Global();
Handle<String> funcName = CStringToString(bstrFuncName);
Handle<Value> funcValue = global->Get(funcName);
Handle<Function> func = Handle<Function>::Cast(funcValue);
//准备参数
const UINT argNum = (pDispParams != NULL) ? (pDispParams->cArgs) : (0);
Handle<Value> *vals = new Handle<Value>[argNum];
for (UINT i=0; i<argNum; i++) {
vals[i] = ToValue(pDispParams->rgvarg[argNum-i-1]);
}
//调用
Handle<Value> result = func->Call(global, argNum, vals);
两种JS引擎的基本使用方法就先介绍到这里,在下一篇将介绍一下V8引擎的回调机制

转载自http://blog.csdn.net/yinbo18120/archive/2009/06/05/4240769.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: