我们知道实现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. laravel 导出插件

    转发:https://blog.csdn.net/gu_wen_jie/article/details/79296470 版本:laravel5 php 5.6 安装步骤: 一.安装插件 ①.首先在L ...

  2. c语言数组相关的计算

    1.数组的创建:元素类型 数组名 [常量或者常量表达式] 如:int arr1[10];注:即使是被const修饰的变量也不能作为[]中的内容,它本质上依然属于变量,只是具有常量属性2.数组的初始化: ...

  3. thinphp5会员注册邮箱验证

    1.首先完成邮箱发送http://www.cnblogs.com/jcydd/p/7299750.html 2.在完成会员新增后执行后置函数,在模型类当中 //注册后置函数 protected sta ...

  4. Eclipse进行Java web开发时,可能会出现这样的错误:The superclass javax.servlet.http.HttpServlet was not found on the Java Build Path

    我们遇到的错误显示如下:   我们右击有错误提示的文件夹,如下:   我们点击”配置构建路径“,如下:   我们再点击”添加库“,如下:   我们选中上图中标出的选项,再点击下一步,如下:   我们再 ...

  5. 判断当前用户是否在某个SharePoint组内

    /// <summary> /// 判断当前登录人是否在sharepoint组中 /// </summary> /// <param name="current ...

  6. @Import @bean,@Conditional @ConfigurationProperties @EnableConfigurationProperties 注解使用

    一分钟学会spring注解之@Import注解http://blog.51cto.com/4247649/2118354 @Autowired与@Resource 注解的使用 https://www. ...

  7. LeetCode 128 Longest Consecutive Sequence 一个无序整数数组中找到最长连续序列

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence.Fo ...

  8. android 缓存路径

    用程序在运行的过程中如果需要向手机上保存数据,一般是把数据保存在SDcard中的.大部分应用是直接在SDCard的根目录下创建一个文件夹,然后把数据保存在该文件夹中.这样当该应用被卸载后,这些数据还保 ...

  9. 牛客网训练赛26D(xor)

    题目链接:https://www.nowcoder.com/acm/contest/180/D 线性基的学习:https://www.cnblogs.com/vb4896/p/6149022.html ...

  10. 宋宝华:swappiness=0究竟意味着什么?

    http://mp.weixin.qq.com/s/BixMISiPz3sR9FDNfVSJ6w 本文解释swappiness的作用,以及swappiness=0究竟意味着什么. 内存回收 我们都知道 ...