快捷搜索:

COM原理及应用----COM特性

1、面向工具系统的三个最基础的特点

封装性、多态性、重用性。

2、COM特点的概述

COM工具的封装特点是很彻底的,所有的工具状态信息必须经由过程接谈锋能造访;而COM的多态性完全经由过程接口表现出来,而且,COM分手在三个层次上表现了多态性:接口成员函数、单个接口、一组接口(工具种别即 implemented category)。而COM的重用性相对繁杂。

3、重用性

所谓重用性是指,当一个法度榜样单元能够对其他的法度榜样单元供给功能办事时,尽可能地重用本来法度榜样单元的代码,既可以在源代码一级重用,也可以在可履行代码一级重用。

C++说话的重用性位于源代码一级,一个类可以承袭于另一个类,从而把父类的功能重用。但对付COM组件则情形有所不合,由于COM是建立在二进制代码根基上的标准,以是其重用性也一定建立于二进制代码一级。

COM重用性是指一个COM工具若何重用已有的COM工具的功能,而不是重复实现老的功能办事。按照COM的标准,实现这种重用性有两条道路:包涵和聚合。

4、包涵和聚合

工具B调用工具A的响应成员函数实现ISomeInterface接口。是以,工具B的ISomeInterface接口供给的功能可以跨越工具A的接口功能,返回结果也可以不同等。以致,工具B的接口与工具A的接口不必然相同。一样平常来说,工具A的生计期包孕在工具B的生计期之内。

在聚合模型中,被聚合的工具A虽然直接向工具B的客户法度榜样供给功能办事,但它的生计期仍受工具B节制,而且其他的一些行径也受工具B的节制,包括内部状态初始化、获取数据等等。

为了使聚合能够顺利实现,工具A必须能够适应在被聚合的环境下进行特殊的处置惩罚,尤其是接口的QueryInterface成员函数,在被聚合环境下,当客户哀求它所不支持的接口或者IUknown接口时,它必须把节制交给外部工具,由外部工具抉择客户法度榜样的哀求结果。

聚合涉及到聚合工具和被聚合工具双方的协作,并不是每个工具都能够支持聚合特点,但聚合表现了组件软件真正意义上的重用。而包涵的重用性完全建立在客户/办事器模型相对性的根基上,实际上也便是客户法度榜样和组件法度榜样的嵌套关系。这是包涵和聚合本色的不合。

5、委托IUnknown和非委托IUnknown

工具创建函数CoCreateInstance的第二个参数pUnknownOuter用于办理聚合中IUnknown接口的问题。当其为NULL时表指正常应用,不为NULL时被聚合应用。内部工具实现两个IUnknown 分手用于这两种环境:委托IUnknown和非委托IUnknown(delegating unknown和nondelgating unknown)。

按照平日应用要领实现的IUnknown为非委托IUnknown,而委托IUnknown在不合的环境下有不合的行径:当工具被正常应用时,委托 IUnknown把调用通报给工具的非委托IUnknown;当工具被聚合应用时,委托IUnknown把调用通报到外部工具的IUnknown接口,即工具被创建时通报进来的pUnkownOuter参数,并且,这时外部工具经由过程非委托IUnknown对内部工具进行节制。委托IUnknown本身不进行任何操作。

由于C++类不支持同时实现两个IUnknown,以是委托IUnknown和非委托IUnknown不能都应用IUnknown类,但我们可以定义一个新的类。由于COM不是经由过程类名来识别接口,而是经由过程vtable来调用接口成员函数。

6、COM接口调用的进程透明性

客户法度榜样创建COM工具具有进程透明特点,不管是进程内组件照样进程外组件,客户法度榜样可以应用同等的措施创建COM工具。对付进程内组件,无论是创建历程,照样客户法度榜样对接口函数的调用历程,都可以按照一样平常的同一进程内部函数调用的历程来理解组件和客户之间的交互操作;但对付进程外组件,实际的情形要繁杂得多,由于组件法度榜样户法度榜样拥有不合的进程空间,以是,它们之间所有的交互历程都涉及到进程之间的通信历程。然而,COM客户法度榜样创建进程外组件法度榜样成功后,它就获得了组件工具的一个接口指针,经由过程该指针间接调用组件工具的成员函数,犹如调用本进程内的函数一样,这恰是COM所期望达到的透明效果。

对指针的列集处置惩罚历程是:列集时,把指针所指的数据装到数据包中;散集时,在进程平分配一块内存,把数据包中的数据拷贝到内存中,所得内存的地址即为散集的结果。

假如函数的参数中包孕了指向接口的指针,则情形要繁杂得多。接口的列集包孕了代理工具和存根代码的创建历程,实际上接口指针的列集历程也包括了连接的创建历程。

11、列集历程的两种实现要领:

自定义列集法(custom marshaling),也称为基础列集法(basic marshaling architecture)。其列集历程完全由工具自身节制,工具指定其代理工具的CLSID,代理工具节制了其所有接口的列集历程,包括接口参数的列集和散集,以及代理工具和存根代码之间的跨进程通信历程。

标准列集法(standard marshaling),是由COM供给缺省的代理工具和存根代码,由于列集历程涉及到操作系统的一些繁杂特点的编程,如共享内存操作或其他跨进程数据传输机制,以致经由过程收集协议传输数据,以是COM供给了缺省的代理和存根代码以及一套标准的列集措施,可以处置惩罚常用数据类型的列集和散集,包括指针类型和接口指针类型。

标准列集法的道理以及其列集历程与自定义列集法完全同等,事实上标准列集法是自定义列集法的一个特例。但两者有一个基础的不合:自定义列集法其列集历程完全由工具自身节制,以是它以全部工具为列集单位,即工具指定的代理工具和存根代码必须处置惩罚工具支持的所有接口;而标准列集法应用COM供给的标准代理工具和存根代码,实际上该代理工具和存根代码只是列集历程的治理器,是以,标准列集法因此接口为列集单位,COM供给的很多标准接口,其列集历程已经过COM 库供给了,法度榜样员只必要供给自定义接口的列集代码即可。

假如一个进程外组件实现了多个COM接口,那么是否必要为每一个接口实现其代理/存根组件法度榜样呢?在这些接口中,假如它是COM供给的标准接口,或者是 OLE标准接口,则COM或者OLE已经供给了其代理/存根法度榜样,我们可以不管这些接口,直接应用即可;假如自定义的接口,则必须自己实现代理/存根法度榜样,并注册到系统中,然后才能真正应用这些接口。

13、自定义接口的代理/存根法度榜样的实现

Microsoft供给了MIDL实用对象赞助我们建立自定义接口的代理/存根法度榜样。首先我们应用IDL(接口描述说话)说话建立接口描述文件,然后运行 MIDL对象,它会根据接口描述文件天生一些C说话源代码文件,用这些源代码文件可以创建代理/存根组件法度榜样。它为我们供给了接口代理/存根组件的一种标准实现措施。

用IDL描述接口与C++描述接口有一些相似之处,但IDL是一种平台无关的标准化描述说话。Win32 SDK供给了所有COM或者OLE标准接口的IDL描述,包括unknown.idl(定义了IUnknown接口),可以在Visual C++的include目录下找到这些IDL文件。Microsoft的RPC开拓包中包括运行法度榜样MIDL.EXE和接口列集应用的 RpcProxy.h、Unknown.idl和wtypes.idl,以及RPC调用所必要的静态连接库和动态连接库。

一样平常地,用MIDL法度榜样可以孕育发生实现代理/存根组件法度榜样所必要的所有C说话源代码文件:奸淫.h为接口阐明头文件;奸淫_p.c为接口代理和存根的实现文件;奸淫_i.c为定义所有GUID描述符的文件;dlldata.c包孕代理/存根法度榜样的进口函数及类厂所需的数据布局。

运行NMAKE法度榜样可以天生代理/存根组件法度榜样,在集成开拓情况中也可以天生。在集成开拓情况中创建一个工程,并把MIDL天生的源代码文件的DEF文件加入到工程中,并在编译选项中加入REGISTER_PROXY_DLL,在连接选项中加入rpcrt4.lib、uuid.lib。

(5)       进行所有的剖断并对数据包加密。

20、COM供给了两种类型的安然性

激活安然性(activation security),不合于引发安然性(launch security),包括COM工具若何被安然地启动、客户若何与工具建立连接,以及若何保护公共的资本,比如全局运行工具表、系统注册表等。

调用安然性(call security),是指在已经建立连接的根基上,客户调用组件法度榜样的安然保护问题。

21、激活安然性

SCM是COM库中认真找到并启动组件法度榜样的组件。当客户向COM库哀求创建新的COM工具或者连接已经运行的组件工具时,认真处置惩罚哀求的恰是SCM。是以,激活安然性也经由过程SCM实现。

激活安然性是进程一级的安然性,即进程中所有的工具和所有工具的成员函数共享的安然性,它分两种环境:静态安然性和动态安然性。当SCM接管到激活工具的哀求时,它反省注册表中安然设置设置设备摆设摆设信息,以便满意合法用户的哀求,这称为静态安然性反省;另一种环境是,在法度榜样运行历程中设置进程的安然性,这称为动态安然性反省。

Windows供给的对象DCOMCNFG.EXE(在节制面板中)可以对组件的安然性进行设置。

22、调用安然性

调用安然性的实现措施之一是应用IClientDecurity接口,措施二是应用COM供给的API函数。IClientDecurity是接口代理选择实现的接口,它的三个主要成员函数:CopyProxy、QueryBlanket和SetBlanket。COM供给了几个API函数封装了接口 IClientDecurity的调用:CoQueryProxyBlanket、CoSetProxyBlanket和CoCopyProxy。

MIDL天生的接口代理工具实现了IClientDecurity接口,并且系统代理治理器也实现了IClientDecurity接口,以是并不必要自己实现IClientDecurity接口。

26、不合线程模型(客户线程与工具线程的不合组合)对列集和同步的不合要求

(1)客户和工具运行在不合的进程中。客户调用进程外组件老是要经由过程代理和存根,以是列集是必须的。是以,COM自动实现了调用的同步处置惩罚,工具不必进行同步处置惩罚。

(2)客户和工具运行在同一个线程中。与工具处于同一线程中的客户调用工具老是直接进行的,而且同一线程中的调用弗成能冲突,以是客户调用即不必要列集,而且工具也不必进行同步处置惩罚。

(3)客户和工具运行在同一个进程中,工具运行在套间线程中,客户运行在另一个套间线程或自由线程中。由于工具运行在它自己的套间线程中,以是客户调用总必要列集处置惩罚,COM自动实现同步处置惩罚,工具不必斟酌同步。COM会自动为我们实现接口指针的列集处置惩罚,我们也可以自己对接口指针进行列集处置惩罚。

(4)客户和工具运行在同一个进程中,工具运行在自由线程中,客户运行在另一个套间线程或自由线程中。当客户调用自由线程中的工具时,虽然工具被自由线程所创建,但调用实际上在客户线程中履行,以是客户对接口的调用是直接进行的,是以接口列集是不需要的,但工具必须自己处置惩罚同步,由于多个客户有可能同时调用接口成员函数。

27、套间线程

在套间线程的主函数中有一个消息轮回,而且主函数必须对COM库进行初始化。COM在套间线程中创建了一个暗藏的窗口,主函数的消息轮回认真接管消息并分发消息(包括客户对工具的调用的消息)。

对付运行在套间线程中的COM工具来说,由于这样的工具只能被此线程造访,其他的线程只能经由过程代理/存根调用接口函数,以是工具可以不必担心同步问题,但工具仍旧必要保护全局变量,由于工具的成员函数被所有的同类工具所共享,因而函数有可能会重入。进程内组件DLL法度榜样的进口在多线程情况下有可能被同时造访到,是以,这些入库函数如DllGetClassObject和 DllCanUnliadNow仍旧必要进行同步处置惩罚,以包管多线程造访时不会发生冲突。进一步来讲,DLL组件法度榜样的类厂也必须满意必然的要求,以包管多个线程同时造访类厂工具时不会激发冲突问题,尤其当用类厂工具创建多个组件工具时,类厂必须是线程安然的,即内部供给了同步处置惩罚。使类厂线程安然只需对引用计数操作进行同步保护即可。

您可能还会对下面的文章感兴趣: