如何调用IDispatch接口的方法和属性

我们知道在C/C++语言中有函数,与函数对应的有函数指针。我们可以把一个函数指针传给一个过程,从而实现回调。

那么在脚本语言(如JavaScript)中,可以用"function"来定义一个函数,但与之相对应的却没有函数指针的概念。那么如何将这个函数传给某个过程,来实现回调的功能呢?事实上,在JavaScript中,常常将函数直接传递给一个组件的方法,实现回调。那么,反过来我们问一下,JavaScript将这个函数传入组件,到底是一个什么样的参数类型呢?

传入的参数类型即可以是IDispatch*,也可以是VARIANT(包装的仍是一个IDispatch*值)。这个函数,本质上是一个实现了IDispatch接口的对象,通过访问IDispatch接口的第一个方法,也就实现了对这个函数的回调调用。

下面的函数CCuteTools::AutoWrap以可变参数的形式,实现了对IDispatch接口中方法和属性的调用。
在写出源代码之前,我们先举一个调用它的例子。
CComPtr<IDispatch> pDispCallback; //需要回调的IDispatch接口 
CComVariant vParam1="test";    //准备接收的参数1
CComVariant vParam2=(long)1234;     //准备接收的参数2

CCuteTools::AutoWrap(DISPATCH_METHOD,NULL,pDispCallback,NULL,2,vParam2,vParam1);

//

//采用的是可变参数的形式
HRESULT CCuteTools::AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
    LPOLESTR ptName, int cArgs...)
{
 // Begin variable-argument list...
 va_list marker;
 va_start(marker, cArgs);

 HRESULT hr=AutoWrap(autoType,pvResult,pDisp,ptName,cArgs,marker);
 
 // End variable-argument section...
 va_end(marker);
 
 return hr;
}

//
HRESULT CCuteTools::AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
    LPOLESTR ptName, int cArgs,va_list& marker)
{
 //
 if(!pDisp) {
  return E_FAIL;
 }

 // Variables used...
 DISPPARAMS dp = { NULL, NULL, 0, 0 };
 DISPID dispidNamed = DISPID_PROPERTYPUT;
 DISPID dispID;
 HRESULT hr;

 if(ptName==NULL)
 {
  dispID=0;
 }
 else
 {
 
  // Get DISPID for name passed...
  hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT,
         &dispID);
  if(FAILED(hr)) {
    return hr;
  }
 }

 // Allocate memory for arguments...
 VARIANT *pArgs = new VARIANT[cArgs+1];

 // Extract arguments...
 for(int i=0; i<cArgs; i++) {
   pArgs[i] = va_arg(marker, VARIANT);
 }
 
 // Build DISPPARAMS
 dp.cArgs = cArgs;
 dp.rgvarg = pArgs;
 
 // Handle special-case for property-puts!
 if(autoType & DISPATCH_PROPERTYPUT) {
   dp.cNamedArgs = 1;
   dp.rgdispidNamedArgs = &dispidNamed;
 }
 
 // Make the call!
 CComVariant vResult;
 hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType,
      &dp, &vResult, NULL, NULL);
 if(FAILED(hr)) {
  delete [] pArgs;
   return hr;
 }
 
 if(pvResult!=NULL)
 {
  vResult.Detach(pvResult);
 }
 
 delete [] pArgs;
 
 return hr;
}

 
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
因文件超过20M不能上传,所以拆分为两个文件分次上传 第1章 COM背景知识 1.1 COM的起源 1.1.1 软件业面临的挑战 1.1.2 传统解决方案 1.1.3 面向对象程序设计方法 1.1.4 最终解决方案:组件软件 1.1.5 面向对象的组件模型——COM 1.2 COM的发展历程 1.2.1 COM以前的对象技术:DDE、OLE 1、VBX控件 1.2.2 COM首次亮相:OLE2 1.2.3 Microsoft拥抱Internet:ActiveX 1.2.4 更多的新名词:Windows DNA和COM+ 1.2.5 远程对象:ORBs和DCOM 1.2.6 COM的最新版本:COM+ 1.3 COM技术现状 1.3.1 COM与CORBA 1.3.2 COM与Enterprise Java Beans 1.3.3 Windows之外的COM 小结 第2章 从C++到COM 2.1 C++客户重用C++对象——例程DB 2.1.1 C++对象 2.1.2 客户程序 2.2 将C++对象移进DLL中——例程DB_cppdll 2.2.1 成员函数的引出 2.2.2 内存分配 2.2.3 Unicode/ASCII兼容 2.2.4 例程实现 2.2.4.1 修改接口文件 2.2.4.2 修改对象程序 2.2.4.3 修改客户程序 2.3 C++对象使用抽象基类——例程DB_vtbl 2.3.1 问题:私有数据成员被暴露 2.3.2 解决方案:抽象基类 2.3.2.1 什么是抽象基类(Abstract Base Class) 2.3.2.2 实现秘诀:虚函数(Virtual Functions) 2.3.3 使用抽象基类 2.3.4 例程实现 2.3.4.1 修改接口文件 2.3.4.2 修改对象程序 2.3.4.3 修改客户程序 2.4 改由COM库装载C++对象——例程dbalmostcom 2.4.1 COM库 2.4.2 对象创建的标准入口点 2.4.3 标准对象创建API 2.4.4 标准对象注册 2.4.5 例程实现 2.4.5.1 修改接口文件 2.4.5.2 修改对象程序 2.4.5.3 修改客户程序 2.5 将C++对象变成COM对象 2.5.1 引用计数 2.5.2 多接口 2.5.3 IUnknown接口 2.5.4 标准类厂接口:IClassFactory 2.5.5 对象代码的动态卸载 2.5.6 自动注册 2.5.7 例程实现 2.5.7.1 修改接口文件 2.5.7.2 修改对象程序 2.5.7.3 修改客户程序 2.6 为COM对象添加多接口支持 2.6.1 多接口 2.6.2 DEFINE_GUID 2.6.3 例程实现 2.6.3.1 修改接口文件 2.6.3.2 修改对象程序 2.6.3.3 修改客户程序 小结 第3章 COM基础知识 3.1 对象与接口 3.1.1 COM对象 3.1.2 COM接口 3.1.3 IUnknown接口 3.1.3.1 生存期控制:AddRef和Release 3.1.3.2 接口查询:QueryInterface 3.1.4 全球唯一标识符GUID 3.1.5 COM接口定义 3.1.6 接口描述语言IDL 3.2 COM应用模型 3.2.1 客户/服务器模型 3.2.2 进程内组件 3.2.3 进程外组件 3.2.4 COM库 3.2.5 HRESULT返回值 3.2.6 COM与注册表 3.3 COM组件 3.3.1 实现类厂对象 3.3.2 类厂对象的创建 3.3.3 实现自动注册 3.3.4 实现自动卸载 3.4 COM客户 3.4.1 COM对象创建函数 3.4.1.1 CoGetClassObject 3.4.1.2 CoCreateInstance 3.4.1.3 CoCreateInstanceEx 3.4.2 如何调用进程内组件 3.4.3 COM客户调用进程外组件 3.5 进一步认识COM 3.5.1 可重用机制:包容和聚合 3.5.2 进程透明性 3.5.3 安全性机制 小结 第4章 COM扩展技术 4.1 可连接对象机制 4.1.1 客户、接收器与可连接对象 4.1.1.1 接收器 4.1.1.2 可连接对象 4.1.1.3 客户 4.1.2 实现可连接对象 4.1.3 实现接收器 4.1.4 建立接收器与连接点的连接 4.1.5 获得出接口的类型信息 4.2 结构化存储 4.2.1 什么叫结构化存储和复合文件 4.2.2 存储对象和IStorage接口 4.2.2.1 IStorage接口 4.2.2.2 获得IStorage指针 4.2.2.3 释放STATSTG内存 4.2.2.4 枚举存储对象中的元

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值