COM组件设计与应用(十一)——IDispatch及双接口的调用

本文配套源码

一、前言

前段时间,由于工作比较忙,没有能及时地写作。其间收到了很多网友的来信询问和鼓励,在此一并表示感谢。咳......我也需要工作来养家糊口呀......

上回书介绍了两种方法来写自动化(IDispatch)接口的组件程序,一是用 MFC 方式编写“纯粹”的 IDispatch 接口;二是用 ATL 方式编写“双接口”的组件。

二、IDispatch 接口和双接口

使用者要想调用普通的 COM 组件功能,必须要加载这个组件的类型库(Type library)文件 tlb(比如在 VC 中使用 #import)。然而,在脚本程序中,由于脚本是被解释执行的,所以无法使用加载类型库的方式进行预编译。那么脚本解释器如何使用 COM 组件那?这就是自动化(IDispatch)组件大显身手的地方了。IDispatch 接口需要实现4个函数,调用者只通过这4个函数,就能实现调用自动化组件中所有的函数。这4个函数功能如下:

HRESULT GetTypeInfoCount(

[out] UINT * pctinfo)

组件中提供几个类型库?当然一般都是一个啦。

但如果你在一个组件中实现了多个 IDispatch 接口,那就不一定啦(注1)

HRESULT GetTypeInfo(

[in] UINT iTInfo,

[in] LCID lcid,

[out] ITypeInfo ** ppTInfo)

调用者通过该函数取得他想要的类型库。

幸好,在 99% 的情况下,我们都不用关心这两个函数的实现,因为 MFC/ATL 都帮我们完成了默认的一个实现,如果是自己完成函数代码,甚至可以直接返回 E_NOTIMPL 表示没有实现。(注2)

HRESULT GetIDsOfNames(

[in] REFIID riid,

[in,size_is(cNames)] LPOLESTR * rgszNames,

[in] UINT cNames,

[in] LCID lcid,

[out,size_is(cNames)] DISPID * rgDispId)

根据函数名称取得函数序号,为调用 Invoke() 做准备。

所谓函数序号,大家去观察双接口 IDL 文件和 MFC 的 ODL 文件,每一个函数和属性都会有 [id(序号)....] 这样的描述。

HRESULT Invoke(

[in] DISPID dispIdMember,

[in] REFIID riid,

[in] LCID lcid,

[in] WORD wFlags,

[in,out] DISPPARAMS * pDispParams,

[out] VARIANT * pVarResult,

[out] EXCEPINFO * pExcepInfo,

[out] UINT * puArgErr)

根据序号,执行函数。

使用 MFC/ATL 写的组件程序,我们也不必关心这个函数的实现。如果是自己写代码,则该函数类似如下实现:

switch(dispIdMember)

{

case 1: .....; break;

case 2: .....; break;

....

}

其实,就是根据序号进行分支调用啦。(注3)

从 Invoke() 函数的实现就可以看出,使用 IDispatch 接口的程序,其执行效率是比较低的。ATL 从效率出发,实现了一种叫“双接口(dual)”的接口模式。下面我们来看看,到底什么是双接口:

图一、双接口(dual) 结构示意图

时间: 2024-11-02 11:24:09

COM组件设计与应用(十一)——IDispatch及双接口的调用的相关文章

COM组件设计与应用(九)——IDispatch接口for VC6.0

本文配套源码 一.前言 终于写到了第九回,我也一直期盼着写这回的内容耶,为啥呢?因为自动化(automation)是非常常用.非常有用.非常精彩的一个 COM 功能.由于 WORD.EXCEL 等 OFFICE 软件提供了"宏"的功能,就连我们使用的VC开发环境也提供了"宏"功能,更由于 HTML.ASP.JSP 等都要依靠脚本(Script)的支持,更体现出了自动化接口的重要性. 如果你使用 vc6.0 的开发环境,请继续阅读. 如果你使用 vc.net 2003

COM组件设计与应用(一)起源及复合文件

一.前言 公元一九九五年某个夜黑风高的晚上,我的一位老师跟我说:"小杨呀,以后写程序就和搭积木一样啦.你赶快学习一些OLE的技术吧......",当时我心里就寻思 :"开什么玩笑?搭积木方式写程序?再过100年吧......",但作为一名听话的好学生,我开始在书店里"踅摸"(注1)有关OLE的书籍(注2).功夫不负有心人,终于买到了我的第一本COM书<OLE2 高级编程技术>,这本800多页的大布头花费了我1/5的月工资呀......

Asp.net组件设计浅论

asp.net|设计 一.什么是组件? 查看MSDN,微软是这样给组件定义的:在 .NET Framework 中,组件是指实现 System.ComponentModel.IComponent 接口的一个类,或从实现 IComponent 的类中直接或间接派生的类.这是从纯语言(技术)角度下的定义,通俗的讲,组件是"可独立运作的软件单元",这里强调独立运作,也就代表着组件必须拥有低耦合性.高重用性等特点.微软将软件划分为两部分:其一是Component,意指具备特定功能.可独立运作.

漫谈Visual C#的组件设计方法

visual|设计 Properties 在C#中为类预定义属性是件再简单不过的事,见程序1. 程序1 using System;namespace PropertiesDemo{ public class MyData { ............... } public class Class1 { private MyData _data; public MyData Data { get { return _data; } } public Class1() { _data = new

COM组件设计与应用(六)——用ATL写第一个组件(vc.net)

一.前言 1.与 <COM 组件设计与应用(五)>的内容基本一致.但本回讲解的是在 vc.net 2003 下的使用方法,即使你不再使用vc6.0,也请和上一回的内容,参照比对. 2.这第一个组件,除了所有 COM 组件必须的 IUnknown 接口外,我们再实现一个自己定义的接口 IFun,它有两个函数: Add()完成两个数值的加法,Cat()完成两个字符串的连接. 3.下面......好好听讲! 开始了:-) 二.建立 ATL 工程 步骤2.1:建立一个解决方案. 步骤2.2:在 该解决

AOP@Work: 用Contract4J进行组件设计-用契约式设计和AspectJ改进软件

简介:契约式设计(Design by Contract)是切实可行的技术,可以阐明组 件 设计的细节.为客户记录正确的组件用法,并用编程的方式测试组件使用的顺应 性(compliance).在 AOP@Work 的最后一篇中,Dean Wampler 介绍 了 Contract4J,这是契约式设计的工具,它用 Java 5 标注 (annotation)指定合约,并在运行时用 AspectJ 方面计算合约.在成为 AOP 工具包中新增的一个举足轻重的工具的同时,Contract4J 迎合了面向方

来自极客标签10款最新设计素材-系列十一

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 来源:GBin1.com 本周我们推荐来自极客标签社区带来的10款免费设计素材,大家可以在这里免费下载你需要的内容.如果你也有更好的作品,欢迎分享到社区中来,在得到帮助的同时,也能与更多人分享来自你的作品. iPad和iPhone 5的免费线框设计 来自Cat Smith的一套免费的ipad和iphone的线框设计,包含了相关PSD文件. 令

COM组件设计与应用(十六)——连接点(vc.net)

本文配套源码 一.前言 上回书介绍了回调接口,在此基础上,我们理解连接点就容易多了. 二.原理 图一.连接点组件原理图.左侧为客户端,右侧为服务端(组件对象) 看着好复杂呀......呵呵,其实简单的紧:(注1) 1.一个 COM 组件,允许有多个连接点对象(IConnectionPoint). 也就是说可以有多个发生"事件"的源头.上图就有3个连接点: 2.管理这些连接点的接口叫"连接点容器"(IConnectionPointContainer). 连接点容器接口

COM组件设计与应用(十五)——连接点(vc6.0)

本文配套源码 一.前言 上回书介绍了回调接口,在此基础上,我们理解连接点就容易多了. 二.原理 图一.连接点组件原理图.左侧为客户端,右侧为服务端(组件对象) 看着好复杂呀......呵呵,其实简单的紧:(注1) 1.一个 COM 组件,允许有多个连接点对象(IConnectionPoint). 也就是说可以有多个发生"事件"的源头.上图就有3个连接点: 2.管理这些连接点的接口叫"连接点容器"(IConnectionPointContainer). 连接点容器接口