IE的Trident引擎下实现C++和Javascript相互调用
我们知道实现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相互调用的更多相关文章
- MySQL数据库InnoDB引擎下服务器断电数据恢复
说明: 线上的一台MySQL数据库服务器突然断电,造成系统故障无法启动,重新安装系统后,找到之前的MySQL数据库文件夹. 问题: 通过复制文件的方式对之前的MySQL数据库进行恢复,发现在程序调用时 ...
- LCOW —— 单一Docker引擎下可同时运行Linux和Windows容器啦!
https://blog.csdn.net/m2l0zgssvc7r69efdtj/article/details/79251059 就在上周,Docker官方的master分支上新增了LCOW(Li ...
- [原创]SOUI GDI+渲染引擎下的字体特效,抛砖引玉
由于SOUI是一种双渲染引擎的DUI库,默认在SKIA渲染引擎下是支持特效字体的,具体请参考DEMO中的源码. 但是使用GDI+渲染时是没有这些特效的,着实比较苦恼,此代抛砖引玉,细节实现 请自己再去 ...
- Mysql InnoDB引擎下 事务的隔离级别
mysql InnoDB 引擎下事物学习 建表user CREATE TABLE `user` ( `uid` bigint(20) unsigned NOT NULL AUTO_INCREMENT, ...
- 【原创】smarty引擎下的导航按钮高亮实现
<?php$_nvaarr = array( array('name'=>'首页','url'=>'company.php?id='), array('name'=>'公司介绍 ...
- [源码解析] PyTorch 分布式 Autograd (6) ---- 引擎(下)
[源码解析] PyTtorch 分布式 Autograd (6) ---- 引擎(下) 目录 [源码解析] PyTtorch 分布式 Autograd (6) ---- 引擎(下) 0x00 摘要 0 ...
- 翻译连载 | 第 9 章:递归(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...
- JS引擎是如何工作的?从调用堆栈到Promise
摘要: 理解 JS 引擎运行原理. 作者:前端小智 原文:JS引擎:它们是如何工作的?从调用堆栈到Promise,需要知道的所有内容 Fundebug经授权转载,版权归原作者所有. 为了保证可读性,本 ...
- MVC项目实践,在三层架构下实现SportsStore-09,ASP.NET MVC调用ASP.NET Web API的查询服务
ASP.NET Web API和WCF都体现了REST软件架构风格.在REST中,把一切数据视为资源,所以也是一种面向资源的架构风格.所有的资源都可以通过URI来唯一标识,通过对资源的HTTP操作(G ...
随机推荐
- 痞子衡嵌入式:恩智浦i.MX RTxxx系列MCU特性介绍(2)- RT685EVKA性能实测(Dhrystone)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RTxxx系列MCU的性能. 在前面的文章 i.MXRTxxx微控制器概览 里,痞子衡给大家简介过恩智浦半导体在2018 ...
- Glance代码分析
V2版本的glance-api采用Proxy的方式来构建对象(对象套对象),有点类似装饰器模式,包裹的顺序是 Auth(外层) -> Notifier -> Policy -> Qu ...
- Codeforces - 102222A - Maximum Element In A Stack - 模拟
https://codeforc.es/gym/102222/problem/F 注意到其实用unsigned long long不会溢出. #include<bits/stdc++.h> ...
- Jade(Pug) 模板引擎使用文档
本篇内容 在 Express 中调用 jade 模板引擎 jade 变量调用 if 判断 循环 Case 选择 在模板中调用其他语言 可重用的 jade 块 (Mixins) 模板包含 (Includ ...
- python文件名匹配
待匹配文件:#FY3D_IPMNT_GBAL_L1_20180516_0003_030KM_MS.HDF 干扰文件:#FY3D_IPMNT_GBAL_L1_20180516_0003_030KM_MS ...
- 架构师分享 Docker 新手入门完全指南
来源:架构师小秘圈 ID:seexmq Docker 最初 dotCloud 公司内部的一个业余项目 Docker 基于 Go 语言 Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案 Do ...
- Luogu P2480 [SDOI2010]古代猪文 卢卡斯+组合+CRT
好吧刚开始以为扩展卢卡斯然后就往上套..结果奇奇怪怪又WA又T...后来才意识到它的因子都是质数...qwq怕不是这就是学知识学傻了.. 题意:$ G^{\Sigma_{d|n} \space C_n ...
- linux下.exe文件的安装与使用
1安装wine 2 安装exe软件:下载应用软件.exe,然后点击右键用wine打开/或者在终端中wine 应用软件.exe即能安装. 卸载exe可以右键点击安装软件中uninstall.exe-用w ...
- windows 7 elasticsearch-5.3.2
# windows elasticsearch- D:\nescafe\elasticsearch-\bin λ java -version java version "1.8.0_121& ...
- Notepad++代码函数快速提示设置
设置——首选项——自动完成