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 ...
随机推荐
- 程序员笔记|详解Eureka 缓存机制
引言 Eureka是Netflix开源的.用于实现服务注册和发现的服务.Spring Cloud Eureka基于Eureka进行二次封装,增加了更人性化的UI,使用更为方便.但是由于Eureka本身 ...
- 网络应用(4):块的概念 | Range
分块来处理,也算是自然的想法,就是化整为零.而于对于文件的下载同样使用这个道理,既可整体下载,也可分块下载. 小程这里以http协议为例,来看一下块的概念与使用. http的range http1.0 ...
- Codeforces - 77B - Falling Anvils - 几何概型
https://codeforc.es/contest/77/problem/B 用求根公式得到: \(p-4q\geq0\) 换成熟悉的元: \(y-4x\geq0\) 其中: \(x:[-b,b] ...
- sqoop 安装与命令
1. 下载: wget http://mirrors.shu.edu.cn/apache/sqoop/1.4.7/sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz 2. 解 ...
- 洛谷P2798 爆弹虐场
P2798 爆弹虐场 题目描述 某年某月某日,Kiana 结识了一名爆弹虐场的少年. Kiana 仗着自己多学了几年OI,所以还可以勉勉强强给这位少年 讲一些自己擅长的题.具体来说,Kiana 先给这 ...
- [Xcode 实际操作]三、视图控制器-(4)使用UINavigationController导航栏和工具栏
目录:[Swift]Xcode实际操作 本文将演示如何显示和隐藏导航视图的导航栏和工具栏 打开第一个视图控制器 import UIKit class FirstSubViewController: U ...
- ligerUI弹出框
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- 历年NOIP真题总结
前言:最近把历年的NOIP真题肝了一遍(还有3个紫题先咕掉了),主要是到1998年的提高组的题.把题目的做题简要思路搁在这儿,一个是为了考前翻一翻,想想自己的哪些思路要梳理的什么什么的,反正怎么说呢, ...
- Oracle 11g 数据类型
1. 字符类型 数据类型 长度 说明 CHAR(n BYTE/CHAR) 默认1字节,n值最大为2000 末尾填充空格以达到指定长度,超过最大长度报错.默认指定长度为字节数,字符长度可以从1字 ...
- Python之PIP安装
Python有两个著名的包管理工具easy_install.py和pip.Python2.7的安装包中自带了easy_install.py,而pip需要手动安装.而在Python3.5之后都是默认安装 ...