我们知道实现C++和Javascript通讯有下表5种接口:

引擎 编写语言 API接口 C、C++与JavaScript交互(变量、函数、类) vc2005编译静态库的大小 示例EXE的大小 执行、解析JavaScript的速度
Google V8 C++ C++ 可以 23.1M 1.1M 最快
Firefox3.5以前 SpiderMonkey C C 可以 1.3M 500K
Firefox高版本SpiderMonkey C++ C 可以 15.3M 1.7M 一般
Webkit  JavaScriptCore C++ C 可以 26.2M 1.4M 一般
IE 未知 COM 可以 未知 100K(没有链接库) 一般

IE的Trident引擎是非开源的,微软JavaScript引擎也是非开源的。微软对外提供了一组COM接口。使用这组COM接口,能够将微软的JavaScript、VBScript嵌入到C、C++、VB、C#等宿主语言中。

说到底其实也没什么好说的,先定义一个 CComPtr<IDispatch> 对象,然后调用其对象的Invoke函数,只要弄清楚他的参数正确的传递就好了。

除此之外该接口还提供有一种简易的方法。

CComPtr<IDispatch> Obj;
CComVariant var(true);
if( FAILED(Obj.Invoke1(L"ReflowDocument", &var)) )
MessageBox(_T("Invoke ReflowDocument failed."));

另外还有Invoke0、Invoke2、InvokeN、GetProperty、PutProperty、GetIDOfName、GetPropertyByName。这些函数的实现都在\VC\atlmfc\include\atlcomcli.h头文件中有声明和实现。

//specialization for IDispatch
template <>
class CComPtr<IDispatch> :
public CComPtrBase<IDispatch>
{
public:
CComPtr() throw()
{
}
CComPtr(_Inout_opt_ IDispatch* lp) throw() :
CComPtrBase<IDispatch>(lp)
{
}
CComPtr(_Inout_ const CComPtr<IDispatch>& lp) throw() :
CComPtrBase<IDispatch>(lp.p)
{
}
IDispatch* operator=(_Inout_opt_ IDispatch* lp) throw()
{
if(*this!=lp)
{
return static_cast<IDispatch*>(AtlComPtrAssign((IUnknown**)&p, lp));
}
return *this;
}
IDispatch* operator=(_Inout_ const CComPtr<IDispatch>& lp) throw()
{
if(*this!=lp)
{
return static_cast<IDispatch*>(AtlComPtrAssign((IUnknown**)&p, lp.p));
}
return *this;
}
CComPtr(_Inout_ CComPtr<IDispatch>&& lp) throw() :
CComPtrBase<IDispatch>()
{
p = lp.p;
lp.p = NULL;
}
IDispatch* operator=(_Inout_ CComPtr<IDispatch>&& lp) throw()
{
if (*this != lp)
{
if (p != NULL)
p->Release(); p = lp.p;
lp.p = NULL;
}
return *this;
}
// IDispatch specific stuff
_Check_return_ HRESULT GetPropertyByName(
_In_z_ LPCOLESTR lpsz,
_Out_ VARIANT* pVar) throw()
{
ATLASSERT(p);
ATLASSERT(pVar);
DISPID dwDispID;
HRESULT hr = GetIDOfName(lpsz, &dwDispID);
if (SUCCEEDED(hr))
hr = GetProperty(dwDispID, pVar);
return hr;
}
_Check_return_ HRESULT GetProperty(
_In_ DISPID dwDispID,
_Out_ VARIANT* pVar) throw()
{
return GetProperty(p, dwDispID, pVar);
}
_Check_return_ HRESULT PutPropertyByName(
_In_z_ LPCOLESTR lpsz,
_In_ VARIANT* pVar) throw()
{
ATLASSERT(p);
ATLASSERT(pVar);
DISPID dwDispID;
HRESULT hr = GetIDOfName(lpsz, &dwDispID);
if (SUCCEEDED(hr))
hr = PutProperty(dwDispID, pVar);
return hr;
}
_Check_return_ HRESULT PutProperty(
_In_ DISPID dwDispID,
_In_ VARIANT* pVar) throw()
{
return PutProperty(p, dwDispID, pVar);
}
_Check_return_ HRESULT GetIDOfName(
_In_z_ LPCOLESTR lpsz,
_Out_ DISPID* pdispid) throw()
{
return p->GetIDsOfNames(IID_NULL, const_cast<LPOLESTR*>(&lpsz), , LOCALE_USER_DEFAULT, pdispid);
}
// Invoke a method by DISPID with no parameters
_Check_return_ HRESULT Invoke0(
_In_ DISPID dispid,
_Out_opt_ VARIANT* pvarRet = NULL) throw()
{
DISPPARAMS dispparams = { NULL, NULL, , };
return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
}
// Invoke a method by name with no parameters
_Check_return_ HRESULT Invoke0(
_In_z_ LPCOLESTR lpszName,
_Out_opt_ VARIANT* pvarRet = NULL) throw()
{
HRESULT hr;
DISPID dispid;
hr = GetIDOfName(lpszName, &dispid);
if (SUCCEEDED(hr))
hr = Invoke0(dispid, pvarRet);
return hr;
}
// Invoke a method by DISPID with a single parameter
_Check_return_ HRESULT Invoke1(
_In_ DISPID dispid,
_In_ VARIANT* pvarParam1,
_Out_opt_ VARIANT* pvarRet = NULL) throw()
{
DISPPARAMS dispparams = { pvarParam1, NULL, , };
return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
}
// Invoke a method by name with a single parameter
_Check_return_ HRESULT Invoke1(
_In_z_ LPCOLESTR lpszName,
_In_ VARIANT* pvarParam1,
_Out_opt_ VARIANT* pvarRet = NULL) throw()
{
DISPID dispid;
HRESULT hr = GetIDOfName(lpszName, &dispid);
if (SUCCEEDED(hr))
hr = Invoke1(dispid, pvarParam1, pvarRet);
return hr;
}
// Invoke a method by DISPID with two parameters
_Check_return_ HRESULT Invoke2(
_In_ DISPID dispid,
_In_ VARIANT* pvarParam1,
_In_ VARIANT* pvarParam2,
_Out_opt_ VARIANT* pvarRet = NULL) throw();
// Invoke a method by name with two parameters
_Check_return_ HRESULT Invoke2(
_In_z_ LPCOLESTR lpszName,
_In_ VARIANT* pvarParam1,
_In_ VARIANT* pvarParam2,
_Out_opt_ VARIANT* pvarRet = NULL) throw()
{
DISPID dispid;
HRESULT hr = GetIDOfName(lpszName, &dispid);
if (SUCCEEDED(hr))
hr = Invoke2(dispid, pvarParam1, pvarParam2, pvarRet);
return hr;
}
// Invoke a method by DISPID with N parameters
_Check_return_ HRESULT InvokeN(
_In_ DISPID dispid,
_In_ VARIANT* pvarParams,
_In_ int nParams,
_Out_opt_ VARIANT* pvarRet = NULL) throw()
{
DISPPARAMS dispparams = { pvarParams, NULL, nParams, };
return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);
}
// Invoke a method by name with Nparameters
_Check_return_ HRESULT InvokeN(
_In_z_ LPCOLESTR lpszName,
_In_ VARIANT* pvarParams,
_In_ int nParams,
_Out_opt_ VARIANT* pvarRet = NULL) throw()
{
HRESULT hr;
DISPID dispid;
hr = GetIDOfName(lpszName, &dispid);
if (SUCCEEDED(hr))
hr = InvokeN(dispid, pvarParams, nParams, pvarRet);
return hr;
}
_Check_return_ static HRESULT PutProperty(
_In_ IDispatch* p,
_In_ DISPID dwDispID,
_In_ VARIANT* pVar) throw()
{
ATLASSERT(p);
ATLASSERT(pVar != NULL);
if (pVar == NULL)
return E_POINTER; if(p == NULL)
return E_INVALIDARG; ATLTRACE(atlTraceCOM, , _T("CPropertyHelper::PutProperty\n"));
DISPPARAMS dispparams = {NULL, NULL, , };
dispparams.rgvarg = pVar;
DISPID dispidPut = DISPID_PROPERTYPUT;
dispparams.rgdispidNamedArgs = &dispidPut; if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH ||
(pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF))
{
HRESULT hr = p->Invoke(dwDispID, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF,
&dispparams, NULL, NULL, NULL);
if (SUCCEEDED(hr))
return hr;
}
return p->Invoke(dwDispID, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
&dispparams, NULL, NULL, NULL);
}
_Check_return_ static HRESULT GetProperty(
_In_ IDispatch* p,
_In_ DISPID dwDispID,
_Out_ VARIANT* pVar) throw()
{
ATLASSERT(p);
ATLASSERT(pVar != NULL);
if (pVar == NULL)
return E_POINTER; if(p == NULL)
return E_INVALIDARG; ATLTRACE(atlTraceCOM, , _T("CPropertyHelper::GetProperty\n"));
DISPPARAMS dispparamsNoArgs = {NULL, NULL, , };
return p->Invoke(dwDispID, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
&dispparamsNoArgs, pVar, NULL, NULL);
}
};

atlcomcli.h部分代码

上面这些其实也都是调用了Invoke函数,当然你如果不想用它帮你封装过的这些函数的话,你可以自行调用比上面这些更原始的Invoke,或者重新封装一下它。

总而言之,当你做这就事的时候一定要不停的查阅MSDN,没了它你就是在蒙着眼睛摸象加自欺欺人。

IE的Trident引擎下实现C++和Javascript相互调用的更多相关文章

  1. MySQL数据库InnoDB引擎下服务器断电数据恢复

    说明: 线上的一台MySQL数据库服务器突然断电,造成系统故障无法启动,重新安装系统后,找到之前的MySQL数据库文件夹. 问题: 通过复制文件的方式对之前的MySQL数据库进行恢复,发现在程序调用时 ...

  2. LCOW —— 单一Docker引擎下可同时运行Linux和Windows容器啦!

    https://blog.csdn.net/m2l0zgssvc7r69efdtj/article/details/79251059 就在上周,Docker官方的master分支上新增了LCOW(Li ...

  3. [原创]SOUI GDI+渲染引擎下的字体特效,抛砖引玉

    由于SOUI是一种双渲染引擎的DUI库,默认在SKIA渲染引擎下是支持特效字体的,具体请参考DEMO中的源码. 但是使用GDI+渲染时是没有这些特效的,着实比较苦恼,此代抛砖引玉,细节实现 请自己再去 ...

  4. Mysql InnoDB引擎下 事务的隔离级别

    mysql InnoDB 引擎下事物学习 建表user CREATE TABLE `user` ( `uid` bigint(20) unsigned NOT NULL AUTO_INCREMENT, ...

  5. 【原创】smarty引擎下的导航按钮高亮实现

    <?php$_nvaarr = array( array('name'=>'首页','url'=>'company.php?id='), array('name'=>'公司介绍 ...

  6. [源码解析] PyTorch 分布式 Autograd (6) ---- 引擎(下)

    [源码解析] PyTtorch 分布式 Autograd (6) ---- 引擎(下) 目录 [源码解析] PyTtorch 分布式 Autograd (6) ---- 引擎(下) 0x00 摘要 0 ...

  7. 翻译连载 | 第 9 章:递归(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  8. JS引擎是如何工作的?从调用堆栈到Promise

    摘要: 理解 JS 引擎运行原理. 作者:前端小智 原文:JS引擎:它们是如何工作的?从调用堆栈到Promise,需要知道的所有内容 Fundebug经授权转载,版权归原作者所有. 为了保证可读性,本 ...

  9. MVC项目实践,在三层架构下实现SportsStore-09,ASP.NET MVC调用ASP.NET Web API的查询服务

    ASP.NET Web API和WCF都体现了REST软件架构风格.在REST中,把一切数据视为资源,所以也是一种面向资源的架构风格.所有的资源都可以通过URI来唯一标识,通过对资源的HTTP操作(G ...

随机推荐

  1. Win10访问不了Samba网络共享的解决办法

    一,首先安装SMB功能 1.打开"应用和功能",选择“程序和功能” 2.选择"开启或关闭windows功能" 3.选中下面红框中三个选项,点击确定,然后重启,就 ...

  2. Git fatal:$'GIT_DIR' too big

    这句表示的是创建的文件的名称太长了,将你需要放置的代码的文件名字改短一些即可!

  3. Docker基本用法

    基本操作命令 列举镜像 # docker images 列举容器 # docker ps 运行容器 # docker run -t --name ubuntu -i ubuntu:14.04 /bin ...

  4. [CentOS7] systemd

    声明:本文主要总结自:鸟哥的Linux私房菜-第十七章.認識系統服務 (daemons),如有侵权,请通知博主 查看当前系统设定的服务启动脚本的类型:ls /usr/lib/systemd/syste ...

  5. python之02数据类型学习-作业练习2

    引用博客地址:http://www.cnblogs.com/yuanchenqi/articles/5782764.html 作业描述: 省 市 县的三层数据通过字典 元祖 列表 保存起来执行程序后 ...

  6. Hibernate单表映射学习笔记之一——hibernalnate开发环境配置

    1.什么是ORM? Object/Relationship Mapping:对象/关系映射 2.写SQL语句不好之处: (1)不同数据库使用的SQL语法不同(PL/SQL.T/SQL) (2)同样的功 ...

  7. 树状数组 洛谷P3616 富金森林公园

    P3616 富金森林公园 题目描述 博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N.每一个巨石有一个海拔高度.而这个山脉又在一个盆地中,盆地里可能会积水,积水也有 ...

  8. BZOJ 4165 矩阵 堆

    先把每个长为$mina$,宽为$minb$的矩阵扔到堆里,然后由于矩阵中的数都是正的,所以我们每取出来一个矩形,,就把他向四个方向扩张一行,再把这新的且更大的四个矩形扔到堆里.注意判重,于是我比较懒用 ...

  9. RMAN restore fails with ORA-01180: can not create datafile 1 (文档 ID 1265151.1)

    http://blog.itpub.net/26655292/viewspace-2131269/ ########Q&A issue1:ORA-01180: can not create d ...

  10. SpringMVC(一) 基础知识+入门案例

    SpringMVC基础知识 1.什么是Springmvc 2.springmvc 框架的原理(必须掌握) 前端控制器.处理器映射器.处理器适配器.视图解析器 3.SpringMVC 入门程序 目的:对 ...