COM原理及应用之可连接对象

1、COM的高级特性

       COM规范中有一些高级特性,如可连接对象、永久存储、一致的数据传输等,使COM规范具有更强的生命力,它们也是OLE的基础,但它们的应用又不仅仅局限于OLE,这些高级特性已经广泛应用于Windows操作系统上。

 

2、入接口、出接口与接收器

       入接口(incoming interface)是组件暴露给客户,被动地监听并为客户请求作出反应的接口。而出接口(outgoing interface)是指组件主动与客户进行通信的接口。

       出接口不是由对象实现的,而是由客户程序来实现,客户实现这些接口,并把接口指针告诉对象,以后对象利用此接口指针与客户进行通信。在客户程序方,实现这些接口的对象被称为接收器(sink)。接收器本身也是一个COM对象,但它往往比较简单,只用于监听处理组件对象的通知或请求。

       客户与对象之间的关系是相对的,入接口和出接口也是一个相对概念,它们只用于通信的一个方向。

 

3、可连接对象

       如果一个COM对象支持一个或多个出接口,则称这样的对象为可连接对象(connectable object),或称为源对象(source)。

       可连接对象的出接口也是COM接口,它包含一组成员函数,每个成员函数代表了一个事件(event)、一个通知(notification)或者一个请求(request)。

 

4、事件、通知与请求

       事件和通知在概念上是完全一致的,只是用在不同的场合,例如在COM对象中当某个属性被改变时,它可以给客户发送一个通知;而当特定事情发生时,比如定时消息或用户鼠标操作发生时,对象产生一个事件,客户程序可以处理这些事件。然而,请求的概念则稍有不同,对象给客户发出请求,它希望客户能提供某些信息,期望客户能有应答。

       从COM规范的意义上来讲,不管是事件、通知还是请求,它们都通过出接口的成员函数来实现。

 

5、客户与可连接对象的关系


       虽然接收器也是一个COM,但它有特殊性,它位于客户程序内部,并不需要通过COM库来创建,所以接收器并不需要CLSID来标识,也不需要类厂,接收器的标识和创建过程完全是客户程序内部的事情。对于客户程序外部而言,接收器也是一个单独的COM对象,它有自己的引用计数,有自己的接口查询方法,即 QueryInterface成员函数。COM只要求接收器是一个独立的COM对象,COM规范对接收器的实现没有任何限制。

       一般可连接对象不应该向接收器对象请求其他的接口,即不应该调用接收器的QueryInterface成员函数。接收器通常专用于某个出接口指针,接收器对象只实现该出接口,当然出接口是基接口(比如IUnknown)除外。

       可连接对象和接收器可以形成一对多或者多对一的关系,也即客户与可连接对象之间可以是一对多或者多对一的关系。

 

6、可连接对象的基本结构


       可连接对象可以支持一个或多个出接口,它通过接口IConnectionPointContainer管理所有的出接口。对应于每个出接口,可连接对象又管理了一个称为连接点(connection point)的对象,每一个连接点对象实现了IConnectionPoint接口,客户通过连接点对象建立接收器与可连接对象的连接。连接点即可以访问可连接对象的内部信息,也可以访问客户方的接收器,而其它可以直接使用可连接对象的引用计数器。

 

7、枚举器

       在COM规范中,枚举器(Enumerator)只是一个概念,没有确定的接口用于规定枚举器的各项操作,这是因为枚举器所枚举的数据单元的类型不确定,所以也无法给出确切的定义。客户程序利用枚举器对COM对象中的数据单元进行枚举操作,枚举器把客户对数据单元的操作进行了标准化,因此,COM对象可以按照标准的方法把数据提供给客户,而不必建立二者之间新的协议。

       因为枚举器对象是一个内部对象,它只需暴露枚举接口,不需要CLSID和类厂,所以枚举器对象的实现比较简单,只需实现枚举操作并控制好引用计数即可。

客户的接收器与源对象的连接点建立连接时,源对象使用连接点枚举器管理连接点对象,连接点对象又用连接枚举器管理连接,通过两层结构建立对象与接收器之间的连接。把源对象与连接点对象分开实现,可以使它们各自保持一定的独立性。源对象与接收器之间的连接具有很好的扩展性,而且连接点对象的独立性也使得COM可连接对象机制更具灵活性和广泛性。

 

8、接收器的实现

       在C++语言中,用一般的类从接口类派生,然后分别实现接口成员函数即可。客户程序在建立连接之前,要先创建接收器对象,因为接收器是客户程序的内部对象,所以在C++语言中可以用new操作符创建接收器对象,然后用此连接器对象建立它与源对象之间的连接。

 

9、事件的激发和处理

       实现事件和请求是可连接对象机制的主要目标。事件即可由源对象的入接口成员函数激发,也可以由用户的某些操作引起,还可以由其它对象或客户调用而引起。总之,在源对象执行过程中,根据需要都可以激发事件或者向客户发出请求,事件和请求在程序逻辑上完全一致。

       由于事件或请求是在每个连接上进行的,只有建立了连接的接收器对象才会收到事件或请求。

       连接点对象和接收器对象肯能位于不同的进程中,甚至在不同的机器环境中。因此,事件从激发到处理不一定是直接的函数调用,这是可连接对象机制与一般回调函数机制的重要不同。只有在单线程模型下,连接点对象才直接调用接收器对象的事件控制函数。从连接点对象到接收器对象之间的通信过程与以前讨论的客户和对象之间的通信过程一样,也符合COM线程模型规范,必要时侯也需要进行列集处理。

 

10、出接口通信连接的建立

       首先客户方通过源对象的IConnectionPointContainer接口得到源对象的出接口IID,并进一步向源对象请求 IProvideClassInfo接口,调用IProvideClassInfo::GetClassInfo成员函数得到ITypeInfo结构,再进一步得到出接口的ITypeInfo结构而获取接口的所有类型信息,包括成员函数、函数参数的个数和参数类型等。类型信息是客户和源对象双方的通信协议标准。

       根据出接口的类型信息在程序运行过程中实现动态接收器对象很不容易。虽然可连接对象提供了完善的双向通信机制,但客户要在运行过程中根据源对象的类型信息响应事件或请求并不容易。为此,OLE发展了COM的可连接对象的机制,它使用IDispatch接口作为出接口,利用IDispatch接口中方法(method)的分发功能实现事件控制函数。IDispatch接口的主要特点是,它可在运行时刻而不是在编译时刻把成员函数与特定的分发ID进行绑定操作,这种特性称为迟绑定(late binging)。IDispatch接口是Microsoft实现自动化技术的基础,现在已经得到了广泛的应用。

 

11、用IDispatch接口作为出接口

       IDispatch接口是自动化对象的基本接口,在高级语言或者脚本语言中,可以直接用符号化的名字即字符串访问自动化对象的属性(property)和方法(method)。使用IDispatch接口有三方面的显著有点:第一,用名字访问属性和方法非常简单易用;第二,自动化对象的IDispatch 接口的vtable是固定的,在有些高级语言或脚本语言中没有指针数据类型,所以在这些语言中描述自定义接口比较困难;第三,IDispatch接口支持迟绑定特性,可以在运行过程中根据名字访问属性或方法。

       COM已经提供了IDispatch接口的代理对象(proxy)和存根对象(stub),所以,使用IDispatch接口作为出接口可直接用于进程外源对象的出接口。

       IDispatch接口把所有的调用都通过其成员函数Invoke来实现,并且它提供了管理属性和方法的分发ID机制,以及一套描述参数和返回值的方法,所以使得运行时刻动态绑定属性和方法并进行参数类型检查成为可能。可以说Invoke函数是自动化对象的命令翻译器。

       根据不同的开发环境和运行环境,实现Invoke函数可以采用不同的方法。如果在编译时刻可以决定客户应该响应那些事件或请求,则可以在程序中建立一张表,把每个事件或请求的分发ID和对应的控制函数作为表项放到表中,把这张表称为事件映射表。MFC的COleControl类使用这种方法处理 ActiveX控制的事件和请求。


       利用IDispatch接口作为出接口可以很好地解决接收器的动态创建过程。利用IDispatch接口作为源对象的出接口,由源对象提供出接口的类型信息,即事件控制函数的所有信息,客户程序根据这些类型信息,在Invoke函数中调用相应的事件控制函数。

 

12、MFC对连接和事件的支持

       (1)MFC实现了连接点类CConnectionPoint,CConnectionPoint实现了IConnectionPoint接口,它用一个数组枚举器管理连接;

       (2)CCmdTarget也提供了一组宏支持连接点对象;

       (3)CCmdTarget类有一个内嵌的结构成员m_xConnPtContainer专门用于存放接口IConnectionPointContainer的vtable和偏移量;

       (4)连接点是可连接对象的核心,但连接点的主要目的是激发事件或发送请求,因此,我们应该对每个事件或请求编写一个激发函数。

       MFC提供了类COleDispatchDriver,他主要用于IDispatch接口的客户方调用操作,利用COleDispatchDriver的成员函数,客户可以创建自动化对象,也可以把COleDispatchDriver对象与某个自动化对象联系起来,更有意义的是,COleDispatchDriver使得IDispatch::Invoke调用的参数处理更为简单。

 

13、用CCmdTarget实现源对象的程序结构图

文章出处:http://www.diybl.com/course/3_program/c++/cppxl/20081118/151933.html

转载于:https://www.cnblogs.com/zhangzh/archive/2008/12/11/1353038.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/381467.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hadoop put命令的格式_HDFS常用命令

一.HDFS命令行Hadoop help命令的使用1.hadoop -help查询所有Hadoop Shell支持的命令2.distcp这是Hadoop下的一个分布式复制程序,可以在不t同的HDFS集群间复制数据,也可以在本地文件间复制数据。hadoop distcp将/test/test.txt文件复制到/test/cp下面&…

python的opencv模块_OpenCV Python - 没有名为cv2的模块(再次)

我刚刚在Ubuntu 14.04上安装了OpenCV 3.0。它的工作原理。 根据官方教程,安装OpenCV。#!/bin/bashd #https://help.ubuntu.com/community/OpenCV version"$(wget -q -O - http://sourceforge.net/projects/opencvlibrary/files/opencv-unix | egrep -m1 -o \&q…

081212 晴

我把今天晚上这边的中国人忘年会取消了 但是应该是需要加班的 争取今天早点回家转载于:https://www.cnblogs.com/loverain/archive/2008/12/12/1353413.html

freemarker html 引入script_HTML编码规范

一、前言HTML作为描述网页结构的超文本标记语言,在百度一直有着广泛的应用。本文档的目标是使HTML代码风格保持一致,容易被理解和被维护。二、代码风格2.1. 缩进与换行​[强制] 使用 4个空格做为一个缩进层级,不允许使用 2个空格 或 tab字符。…

python制作词典_我的词典我做主!python3.5生成自己的词性词典

由于朋友需要做文本分析,前提是要将文本中的名词和动词剔除掉,但没有现成的名词和动词的txt格式的词典。于是找来了一个英汉词典,根据每一行出现的adj、adv、n、prep等,使用正则表达式匹配需要的词性,并将其追加写入到…

微软的几个职位简介

说起来比较惭愧,自己混微软圈子也不短了,但是今天还是第一次认真思考微软的这几个比较常用的职位,SDE、SDET、PM,仅供参考下,网上查的,如果有不对或者不全面的地方,欢迎指教 Dev:正式…

写入null_ArrayList并发写出现Null值

ArrayList并非线程安全的容器,这一点大家可能都非常清楚,但是在并发写入的情况下,不安全的情况具体有哪些,大家是否很清楚呢?本篇文章重点聊一下出现null的情况,然后对于其他并发写的安全做一个简单的叙述我…

c语言函数调用数组_第七讲:C语言基础之函数,第二节,实现汉诺塔

本文约2200字,主要讲了C语言基础之函数,递归,数组作为函数参数以及案例、练习题等。带你进入C语言的世界,入门C语言,后边将持续更新。可以收藏学习。想了解C语言基础之函数,函数的基本概述,函数…

当代国人绝难做到的10件平常事

1、在饭厅中保持低声。无论是在家中,还是在大饭店吃饭,中国人总爱高声喧哗,如果是饮酒,还会扯酒皮,猜拳行令,完全不把旁人放在眼中。因而,在中国,也没有人觉得饭厅噪音得治一治。事实…

仍然报错_only_full_group_by配置,竟让所有应用报错?

推荐学习周一福利到!献上“独家全新”MySQL进阶套餐,简直就是血赚 全网独家的“MySQL高级知识”集合,骨灰级收藏,手慢则无 1. 踩坑经历一个很平常的下午,大家都在埋头认真写bug呢,突然企业微信群里炸锅了&a…

根据录入的计算公式计算_污水处理工程设计入门(10)—堰口计算

呓语:虽然现在很多人会推送很多的快速计算表格,但是我并不想授人以鱼。我希望每一个想学习想入门做污水处理工程设计的人先看懂如何设计,再去想如何快速计算,再去想怎么改进。再者,想想有一天你当领导审图了&#xff0…

DNN SEO专题 (收集)

SEO, 是Search Engine Optimization的缩写, 翻译过来是“搜索引擎优化", 直白说就是“针对搜索引擎所做的优化处理工作”。 是一种利用搜索引擎的搜索规则来提高目的网站在有关搜索引擎( Google, Baidu, Live Search 等) 内提名的方式。它可以给你的网站带来更多的客户访问…

发送请求_发送soap请求调用WSDL

");soap.Append("");soap.Append("");soap.Append("XX系统");soap.Append("");soap.Append(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));soap.Append("");soap.Append("{"LoginName":&qu…

递归函数python有什么特点_Python中的递归

在前面的讲解中,函数的调用通常发生在彼此不同的函数之间。其实,函数还有一种特殊的调用方式,那就是自己调用自己,这种方式称为函数递归调用。 递归,在程序设计中也是一个常用的技巧,甚至是一种思维方式&am…

XML基本知识(三)

XML语法(3)--属性、声明符号、字符数据、注释 属性&#xff1a;提供元素的附加信息。 属性是元素开始标签的一部分。eg: <para keywords"Napoleon,France,history">...</para>注意: 属性由“名”和“值”组成&#xff0c;中间有“”分隔。值由引号包括…

apache实验报告 linux_Linux实验报告

Linux实验报告-源代码编译安装Apache(Tarball文件安装)实验背景&#xff1a;通常GNU组织提供的程序包都是源代码格式&#xff0c;即将软件的所有源码文件先以tar打包&#xff0c;然后再使用gizp或是bzip2压缩&#xff0c;生成一个.tar.gz或是.tar.bz2结尾的软件包&#xff0c;也…

python合并两个文本文件内容_用Python 将两个文件的内容合并成一个新的文件.

一个文件的内容是: Introduction to Programming, Networking Fundamentals, Internetworking Technologies, Platform Technologies, Information Technology for Users, Computer Forensics, Enterprise Networks, Database Technologies 还有一个是: BN108, MN401, MN503, B…

设备场景函数——72个

说明&#xff1a;本类 API 函数&#xff0c;内容均摘自网络&#xff0c;版权归实际作者所有。 CombineRgn 将两个区域组合为一个新区域 CombineTransform 驱动世界转换。它相当于依顺序进行两次转换 CreateCompatibleDC 创建一个与特定设备场景一致的内存设备场景 CreateDC,Cre…

安卓手机突然很卡_你的安卓手机越来越卡?教你4招轻松解决问题!

原标题&#xff1a;你的安卓手机越来越卡&#xff1f;教你4招轻松解决问题&#xff01;现在我们对于手机的使用时间不会特别的长&#xff0c;所以这个更换的速度就比较快。其实是很多的用户换手机是因为比较喜欢用新的手机体验新的科技&#xff0c;不过也还是有很多的用户不是因…

python 导入自己写的类_python中自己的类不能被导入

我自己编写了一个类 class Settings(): def __init__(self): self.screen_width1200 self.screen_height800 self.bg_color(230,230,230) 然后我想在引用 import sys import pygame from settings import Settings def run_game(): pygame.init() ai_settingsSettings() screen…