好文档就是一把金锄头!
欢迎来到金锄头文库![会员中心]
电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

COM原理及组件开发实用教案.ppt

85页
  • 卖家[上传人]:新**
  • 文档编号:590233665
  • 上传时间:2024-09-13
  • 文档格式:PPT
  • 文档大小:2.11MB
  • / 85 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    • 主要主要(zhǔyào)内容内容uCOMCOM的基本原理的基本原理u构件对象模型构件对象模型(móxíng)COM/DCOM(móxíng)COM/DCOMu基于基于COMCOM构件的开发构件的开发第1页/共84页第一页,共85页 uCOM是微软提出的第一个构件模型,源于是微软提出的第一个构件模型,源于OLE: Object Link and Embedding(动态链接和嵌入动态链接和嵌入)uOLE1 采用采用DDE(Dynamic Data Exchange:动态数据交换动态数据交换) 在不同在不同(bù tónɡ)的程序之间进行通信的程序之间进行通信uDDE缺点缺点: 建立在建立在Windows消息机制基础上,效率低、稳定消息机制基础上,效率低、稳定性不好、使用不方便性不好、使用不方便 uCOM是为克服上述不足而出现的是为克服上述不足而出现的 COM 技术技术(jìshù)的发展的发展第2页/共84页第二页,共85页 uCOM定义了客户与构件之间互操作的标准,包括规约与实现定义了客户与构件之间互操作的标准,包括规约与实现(shíxiàn)两个部分两个部分u规约部分定义了构件之间的通信机制,这些规约不依赖于任何特定规约部分定义了构件之间的通信机制,这些规约不依赖于任何特定的语言和操作系统的语言和操作系统u实现实现(shíxiàn)部分就是部分就是COM库,为库,为COM规约的具体实现规约的具体实现(shíxiàn)提供了一些核心服务提供了一些核心服务uCOM仅支持同一台计算机上(当然是仅支持同一台计算机上(当然是Windows操作系统)的互操操作系统)的互操作,不支持分布式计算环境作,不支持分布式计算环境COM 技术技术(jìshù)的发展的发展第3页/共84页第三页,共85页。

      u将将COM技术延伸到分布计算环境,产生了所谓的技术延伸到分布计算环境,产生了所谓的DCOM (Distributed COM,分布构件对象模型分布构件对象模型)u 用网络协议代替用网络协议代替 本地进程之间的通信本地进程之间的通信u 针对分布环境提供了新特性:针对分布环境提供了新特性:u 位置透明位置透明u 网络安全性网络安全性u 跨平台调用跨平台调用 等等u为了满足为了满足(mǎnzú)企业级应用的需求,推出了微软事务服务企业级应用的需求,推出了微软事务服务器器 (MTS: Microsoft Transaction Server),把应用系统的客户程把应用系统的客户程序、应用构件和各种资源有机结合起来,为分布式企业应用序、应用构件和各种资源有机结合起来,为分布式企业应用提供了一种服务器端的构件运行和部署环境提供了一种服务器端的构件运行和部署环境COM 技术技术(jìshù)的发展的发展第4页/共84页第四页,共85页。

      u为了使为了使Windows真正成为企业应用平台,微软推出了分布式真正成为企业应用平台,微软推出了分布式网络应用体系结构(网络应用体系结构(Windows DNA: Distributed interNet Application Architecture),),DNA是一个完整的、多层的企是一个完整的、多层的企业应用体系结构:包含工具业应用体系结构:包含工具(gōngjù)、数据库、操作系统、、数据库、操作系统、编程模型和应用服务等编程模型和应用服务等u随着随着Windows 2000的发布,微软进一步把的发布,微软进一步把COM、、DCOM、、MTS统一起来,形成了真正适合于企业级应用的构件技术:统一起来,形成了真正适合于企业级应用的构件技术:COM+u可以认为:可以认为:COM/DCOM + MTS = COM+uCOM+是一种中间件技术规约,提供操作系统级的分布式是一种中间件技术规约,提供操作系统级的分布式“服务服务”COM 技术技术(jìshù)的发展的发展第5页/共84页第五页,共85页 Window DNA第6页/共84页第六页,共85页 u是一个服务器端的开发平台,包括是一个服务器端的开发平台,包括uWindows NT/2000/2003 提供运行提供运行(yùnxíng)环境和支持环境和支持uCOM/DCOM uMSMQ 消息队列产品,支持构件间异步通信消息队列产品,支持构件间异步通信uMTS 管理构件的应用服务管理构件的应用服务uMicrosoft Wolfpack 支持集群服务器的软件支持集群服务器的软件uMicrosoft SQL Server uMicrosoft IIS Web服务器服务器uMicrosoft Management Console 部署和管理工具部署和管理工具Window DNA第7页/共84页第七页,共85页。

      COM+基本基本(jīběn)结构结构COM+目录(mùlù)负载平衡驻留内存数据库对象池新的事件模型构件管理和部署JIT激活COM+ MTS事务支持资源分发(fēnfā)管理安全模型易于管理远程支持 DCOM分布式构件服务 COM基于接口的编程模型基本的构件服务第8页/共84页第八页,共85页 uCOM((Component Object Model),组件对象模型,是一种以),组件对象模型,是一种以组件为发布单元的对象模型,这种模型使得各个软件组件可以用组件为发布单元的对象模型,这种模型使得各个软件组件可以用一种统一一种统一(tǒngyī)的方式进行交互的方式进行交互uCOM是一种协议,它建立了一个软件模块同另一个软件模块之是一种协议,它建立了一个软件模块同另一个软件模块之间的连接,提供了组件之间进行交互的规范,也提供了实现交互间的连接,提供了组件之间进行交互的规范,也提供了实现交互的环境的环境u当这种连接建立起来后,两个模块之间就可以通过当这种连接建立起来后,两个模块之间就可以通过“接口接口”的机的机制来进行通讯,这些接口既不需要静态的或动态的连接入口点,制来进行通讯,这些接口既不需要静态的或动态的连接入口点,也不需要编码很复杂的地址也不需要编码很复杂的地址什么什么(shén me)是是COM?第9页/共84页第九页,共85页。

      u全局唯一标识符(全局唯一标识符(Global Unique IDentifier)来源于)来源于OSF的通用统的通用统一标识符一标识符UUID((Universal Unique IDentifier),是一个),是一个128位整数位整数u用于标识用于标识COM对象对象(CLSID)和接口和接口(IID)u由于空间足够大由于空间足够大, 冲突较小冲突较小.可以用编程的方法生成具有可以用编程的方法生成具有(jùyǒu)唯一性的唯一性的GUID uVC: UUIDGEN.EXE, GUIDGEN.EXEu对对GUID值的传递通常通过引用进行值的传递通常通过引用进行COM基本概念:基本概念:GUID第10页/共84页第十页,共85页 基本概念:基本概念:COM对象对象(duìxiàng)/COM构件构件/COM接口接口COM构件对象1对象2接口1接口2 接口3接口4第11页/共84页第十一页,共85页 基本概念:基本概念:COM对象对象(duìxiàng)和和COM构构件件u在在COM规约中,规约中,“构件构件”和和“对象对象”经常混淆,所谓经常混淆,所谓COM对对象是指符合象是指符合COM规则规则(guīzé)的的CoClass(构件类)的实例,(构件类)的实例,每一个每一个COM对象都有一个对象都有一个GUID,称为,称为CLSID(CoClassID)uCOM构件是指以编译后的形式提供一组功能的构件是指以编译后的形式提供一组功能的COM对象对象u独立于具体编程语言独立于具体编程语言u一个构件可以由多个类实现一个构件可以由多个类实现u以二进制形式(以二进制形式(DLL或或EXE)发布)发布u可以在不妨碍客户的形式下被升级可以在不妨碍客户的形式下被升级u可以透明地在网络上被重新分配可以透明地在网络上被重新分配第12页/共84页第十二页,共85页。

      uCOM接口是接口是COM规范的核心内容,是规范的核心内容,是COM对象对象(duìxiàng)显示出来显示出来的所有信息,是一组逻辑上相关的函数集合的所有信息,是一组逻辑上相关的函数集合u每一个接口都有一个每一个接口都有一个GUID,称为接口标识符(简称,称为接口标识符(简称IID::Interface IDentifier))uCOM接口具有不变性,只允许单继承接口具有不变性,只允许单继承u一个一个COM对象对象(duìxiàng)可以实现多个接口,这体现了可以实现多个接口,这体现了COM对象对象(duìxiàng)的多态性,这些接口由的多态性,这些接口由IUnknown接口来管理接口来管理u在在C++中中,可以用抽象基类来定义可以用抽象基类来定义COM接口接口基本概念:基本概念:COM接口接口(jiē kǒu)第13页/共84页第十三页,共85页 新版本构件新版本构件(gòujiàn)的处理的处理uCOM接口永远不会变化接口永远不会变化 :一个一个IID就是一个接口,当对组件进就是一个接口,当对组件进行升级时,一般不会修改已有的接口,而是加入一些新接口行升级时,一般不会修改已有的接口,而是加入一些新接口u当下列条件中的任何一个变化时,应给新接口指定新当下列条件中的任何一个变化时,应给新接口指定新IIDu接口中函数数目接口中函数数目u接口中函数顺序接口中函数顺序u某个函数的参数某个函数的参数u某个函数参数的顺序某个函数参数的顺序u某个函数参数的类型某个函数参数的类型u函数可能的返回值函数可能的返回值u函数返回值的类型等函数返回值的类型等u不同版本不同版本(bǎnběn)接口的命名接口的命名:在老名称后加一个数字在老名称后加一个数字第14页/共84页第十四页,共85页。

      u是所有是所有COM对象都必须实现的接口,其它接口都直接或间接继对象都必须实现的接口,其它接口都直接或间接继承承IUnknown((IID为为{00000000-0000-0000-C000-000000000046} ))接口,包含接口,包含(bāohán)三个基本操作三个基本操作uAddRef:提供生存周期管理功能,增加对象引用计数:提供生存周期管理功能,增加对象引用计数uRelease:提供生存周期管理功能,用于释放对象:提供生存周期管理功能,用于释放对象uQueryInterface:负责向客户提供接口查询功能:负责向客户提供接口查询功能基本概念:基本概念:IUnknown接口接口(jiē kǒu)IUknown接口接口(jiē kǒu)的定义,定义在的定义,定义在win32 SDK中的中的UNKNWN.h头文件中:头文件中:interface IUnkown{ virtual HRESULT _stdcall QueryInterface( const IID&, void **ppv) = 0; virtual ULONG_stdcall AddRef() = 0; virtual ULONG_stdcall Release() = 0; }第15页/共84页第十五页,共85页。

      u微软接口定义语言微软接口定义语言MIDL((Microsoft Interface Definition Language)是定义)是定义COM接口的申述式语言接口的申述式语言u通过独立于具体编程语言的方式来定义接口通过独立于具体编程语言的方式来定义接口u该语言基于该语言基于OSF分布式计算环境(分布式计算环境(DCE)远程过程调用()远程过程调用(RPC))的接口描述语言的接口描述语言IDLuCOM规范使用的规范使用的IDL接口描述语言不仅可用于接口描述语言不仅可用于COM接口,同时还接口,同时还定义了一些常用的数据类型,也可描述自定义的数据结构定义了一些常用的数据类型,也可描述自定义的数据结构(shù jù jié ɡòu),对于接口的成员函数,可以指定每个参数的类型、输入输出特,对于接口的成员函数,可以指定每个参数的类型、输入输出特性,甚至可支持变长度的数组的描述性,甚至可支持变长度的数组的描述uMIDL支持指针类型,与支持指针类型,与C/C++类似类似基本概念:接口定义语言基本概念:接口定义语言(yǔyán)第16页/共84页第十六页,共85页 u接口定义例:接口定义例:interface IDictionary{ HRESULT Initialize(); HRESULT LoadLibrary([in] string); HRESULT InsertWord([in] string, [in] string); HRESULT DeleteWord([in] string); HRESULT LookWorld([in] string,[out] string*); HRESULT RestoreLibrary([in] string); HRESULT FreeLibrary();}基本概念:接口定义语言基本概念:接口定义语言(yǔyán)第17页/共84页第十七页,共85页。

      uCOM接口是一个二进制标准,客户同接口的连接并不是通过接口是一个二进制标准,客户同接口的连接并不是通过其名称或其成员函数的名称来实现的,而是通过其在内存块中其名称或其成员函数的名称来实现的,而是通过其在内存块中的位置完成的的位置完成的uCOM接口是一个包含一个函数指针数组的内存结构,每一个接口是一个包含一个函数指针数组的内存结构,每一个数组元素包含的是一个由组件所实现的函数的地址数组元素包含的是一个由组件所实现的函数的地址uC++通过纯抽象基类实现通过纯抽象基类实现COM接口,实际上是定义了一个内接口,实际上是定义了一个内存块的结构,但此内存只是存块的结构,但此内存只是(zhǐshì)在派生类中实现此抽象基类在派生类中实现此抽象基类时才会被分配,派生类继承此抽象基类时将继承此内存结构时才会被分配,派生类继承此抽象基类时将继承此内存结构COM接口接口(jiē kǒu)第18页/共84页第十八页,共85页 Vtbl指针指针虚拟函数表虚拟函数表pIXIX&Fx1&Fx2&Fx3&Fx4虚拟虚拟(xūnǐ)函数表函数表uCOM接口的内存结构同接口的内存结构同C++编译器为抽象基类所生成的内存编译器为抽象基类所生成的内存结构是相同的,对于如下利用结构是相同的,对于如下利用(lìyòng)纯抽象基类方式定义的接纯抽象基类方式定义的接口口uinterface IX {u virtual void _stdcall Fx1()=0;u virtual void _stdcall Fx2()=0;u virtual void _stdcall Fx3()=0;u virtual void _stdcall Fx4()=0; }第19页/共84页第十九页,共85页。

      u提高接口实现的灵活性,实现抽象基类的类可能会将特定于实提高接口实现的灵活性,实现抽象基类的类可能会将特定于实例的信息同例的信息同vtbl一块一块(yī kuài)保存保存例子例子(lì zi):一个实现接口一个实现接口IX的类的类CA,CA包含包含2个数据个数据:class CA : public IX{ public: virtual void_stdcall Fx1() {} virtual void_stdcall Fx2() {} virtual void_stdcall Fx3() {} virtual void_stdcall Fx4() {} double Data1; double Data2;}Vtbl的作用的作用(zuòyòng)第20页/共84页第二十页,共85页 Vtbl指针指针(zhǐzhēn)虚拟虚拟(xūnǐ)函数表函数表IX&Fx1&Fx2&Fx3&Fx4Data1Data2pAFx1Fx2Fx3Fx4CA实例数据实例数据(shùjù)和和vtbl一起保存一起保存u注意:注意:COM组件决不会访问任何实例数据,在组件决不会访问任何实例数据,在COM中,对一中,对一个组件的访问只能通过函数完成,绝不能直接通过变量个组件的访问只能通过函数完成,绝不能直接通过变量u纯抽象基类只有虚拟函数,没有实例数据纯抽象基类只有虚拟函数,没有实例数据第21页/共84页第二十一页,共85页。

      两个两个(liǎnɡ ɡè)实例实例 共享同一共享同一VtblVtbl指针指针虚拟函数表虚拟函数表&Fx1&Fx2&Fx3&Fx4Data1Data2pA1pA2Fx1Fx2Fx3Fx4CAVtbl指针指针Data1Data2共享同一共享同一Vtbl第22页/共84页第二十二页,共85页 Vtbl指针指针虚拟函数表虚拟函数表IXQueryInterfaceAddRefRelease&FxpAQueryInterfaceAddRefReleaseFxCA所有COM接口都必须(bìxū)继承IUnknown接口,支持其定义的三个函数,而且必须(bìxū)是接口vtbl的前三个函数第23页/共84页第二十三页,共85页 uIUnknown * CreateInstance();u创建构件创建构件(gòujiàn)时,客户可以使用时,客户可以使用CreateInstance,而不是而不是newuCreateInstance的定义:的定义:u IUnknown * CreateInstance()u {u IUnknown * pI = static_cast (new foo);u pI -> AddRef();u return pI;u }IUnknown指针指针(zhǐzhēn)的获取的获取第24页/共84页第二十四页,共85页。

      u一个一个COM对象(构件)可以实现多个对象(构件)可以实现多个(duō ɡè)接口接口.u使用使用QueryInterface查询某个构件是否支持某个特定的接口查询某个构件是否支持某个特定的接口u void foo(Iunknown * pI){uIX * pIX = NULL;uHRESULT hr = pI->QueryInterface(IID_IX, u (void **)&pIX);uIf (SUCCEEDED(hr)) {upIX->Fx();u } u}接口接口(jiē kǒu)查询查询第25页/共84页第二十五页,共85页 u假定存在类假定存在类 CA,继承继承(jìchéng)接口接口 IX 与与 IYu HRESULT _stdcall CA:: QueryInterface(const IID& iid, void ** ppv){u if (iid == IID_IUnknown) {u *ppv = static_cast(this); }u else if (iid == IID_IX) {u *ppv = static_cast(this); }u else if (iid == IID_IY) {u *ppv = static_cast(this); }uelse {u *ppv = NULL;u return E_NOINTERFACE; }ustatic_cast(*ppv)->AddRef();ureturn S_OK;u}QueryInterface的实现的实现(shíxiàn)第26页/共84页第二十六页,共85页。

      uQueryInterface返回的总是同一个返回的总是同一个IUnknown指针指针u若客户曾经获取过某个接口若客户曾经获取过某个接口,那么它将总能获取此接口那么它将总能获取此接口u客户可以再次获取已经拥有客户可以再次获取已经拥有(yōngyǒu)的接口的接口u客户可以返回到起始接口客户可以返回到起始接口u若能够从某个接口获取某特定接口若能够从某个接口获取某特定接口,则可以从则可以从(该构件的该构件的)任任意接口获取此接口意接口获取此接口QueryInterface的实现的实现(shíxiàn)规则规则第27页/共84页第二十七页,共85页 u通过函数通过函数AddRefAddRef与与ReleaseRelease实现实现u控制构件的生命期控制构件的生命期u解决内存解决内存(nèi cún)(nèi cún)管理问题管理问题u使构件能够自己将自己删除使构件能够自己将自己删除u使用规则使用规则u返回接口指针之前调用返回接口指针之前调用AddRef;AddRef;u使用完接口之后调用使用完接口之后调用Release;Release;u赋值之后调用赋值之后调用AddRef;AddRef;引用引用(yǐnyòng)计数计数第28页/共84页第二十八页,共85页。

      在什么层次上进行计数(jì shù):构件?对象?接口?构件构件构件引用记数构件引用记数对象引用记数对象引用记数对象引用记数对象引用记数对象对象1对象对象2接口接口接口接口接口接口接口接口接口引用记数接口引用记数接口引用记数接口引用记数接口引用记数接口引用记数接口引用记数接口引用记数引用计数引用计数(jì shù)的实现方式的实现方式第29页/共84页第二十九页,共85页 u函数的参数中使用接口指针变量函数的参数中使用接口指针变量u对于输入参数,被调函数不必改变计数对于输入参数,被调函数不必改变计数u对于输出参数,相当于生成了一个对于输出参数,相当于生成了一个(yī ɡè)(yī ɡè)新的接口指针变量,新的接口指针变量,因此在返回之前,需要使计数增因此在返回之前,需要使计数增1 1u对于输入输出参数,参数修改之前计数减对于输入输出参数,参数修改之前计数减1 1,修改之后计数加,修改之后计数加1 1,若参数未被修改,计数不变,若参数未被修改,计数不变u对于局部接口指针变量,不改变计数对于局部接口指针变量,不改变计数u对于全局接口指针变量,作为参数传给某函数之前,计数增对于全局接口指针变量,作为参数传给某函数之前,计数增1 1,返回之后计数减,返回之后计数减1 1,,C++C++类成员变量为接口指针变量时也采类成员变量为接口指针变量时也采用此规则用此规则引用计数的更详细引用计数的更详细(xiángxì)的规的规则则第30页/共84页第三十页,共85页。

      uCOM构件可以和客户机程序在同一个进程中,也可以在不构件可以和客户机程序在同一个进程中,也可以在不同同(bù tónɡ)的进程中的进程中u前者称为进程内构件前者称为进程内构件(INPROC_SERVER)u后者称为进程外构件后者称为进程外构件(LOCAL_SERVER )u如果是如果是DCOM,进程外构件还包括,进程外构件还包括uCLSCTX_REMOTE_SERVER COM构件构件(gòujiàn)与客户机之间的通信机制与客户机之间的通信机制第31页/共84页第三十一页,共85页 u在在Windows平台上,进程内构件以动态链接库平台上,进程内构件以动态链接库(DLL)形式实现形式实现u由于由于DLL包含一个导出函数表,客户机程序和包含一个导出函数表,客户机程序和DLL动态连接时会建立一动态连接时会建立一张表,把客户机调用和张表,把客户机调用和DLL中函数的地址连接起来中函数的地址连接起来u 因此客户机程序和进程内构件可通过因此客户机程序和进程内构件可通过(tōngguò)直接函数调用进直接函数调用进行交互行交互u进程内构件程序也可称作进程内服务程序进程内构件程序也可称作进程内服务程序COM构件与客户机之间的通信构件与客户机之间的通信(tōng xìn)机机制制第32页/共84页第三十二页,共85页。

      u对于进程外构件对于进程外构件(gòujiàn),由于进程之间相互屏蔽,客户机进,由于进程之间相互屏蔽,客户机进程不能直接调用构件程不能直接调用构件(gòujiàn)进程,需要遵循操作系统对进程进程,需要遵循操作系统对进程间通信所做的规定,在间通信所做的规定,在Windows平台上,进程外构件平台上,进程外构件(gòujiàn)以以EXE实现,实现,COM采用本地过程调用(采用本地过程调用(LPC)作为进程间通信机)作为进程间通信机制制COM构件构件(gòujiàn)与客户机之间的通信机与客户机之间的通信机制制客户机进程客户机应用进程内构件进程内对象COM本地对象代理服务器进程COM本地对象代理COM桩LPC第33页/共84页第三十三页,共85页 u当调用当调用(diàoyòng)组件的时候,其实是依靠代理(运行在本地)组件的时候,其实是依靠代理(运行在本地)和存根(运行在远端)之间的通讯完成的和存根(运行在远端)之间的通讯完成的组件组件(zǔ jiàn)调用机制调用机制第34页/共84页第三十四页,共85页 uCOM不仅定义了客户与构件之间交互的规约,而且提供了全面的不仅定义了客户与构件之间交互的规约,而且提供了全面的实现细节,实现细节,COM的实现与操作系统的实现与操作系统(xìtǒng)密切相关,包括密切相关,包括:uCOM库(库(COM Library))u系统系统(xìtǒng)注册表(注册表(windows registry))u类工厂类工厂uCOM服务器服务器COM的实现的实现(shíxiàn)第35页/共84页第三十五页,共85页。

      u是是COM标准的系统级实现,为标准的系统级实现,为COM对象的标识和创建、内存管理、对象的标识和创建、内存管理、构件程序的卸载等提供了一组标准接口和辅助函数构件程序的卸载等提供了一组标准接口和辅助函数u在在Windows系统中,系统中,COM库主要包含在库主要包含在OLE32.dll、、OLE32.lib和和RPCSS.dll文件中文件中uCOM库很多地方直接用到了库很多地方直接用到了Windows系统的一些特性,例如系统注系统的一些特性,例如系统注册表和动态链接库,册表和动态链接库,COM通过注册表查找通过注册表查找(chá zhǎo)本地服务器本地服务器(即即EXE程序程序) 以及程序名与以及程序名与CLSID的转换的转换 COM库库第36页/共84页第三十六页,共85页 COM库库uCOM库中常用的函数库中常用的函数(hánshù)u初始化函数初始化函数(hánshù)u与与GUID相关的函数相关的函数(hánshù)u对象创建函数对象创建函数(hánshù)u内存管理函数内存管理函数(hánshù)第37页/共84页第三十七页,共85页 u在使用COM库中的其他函数之前,进程必须先调用u HRESULT CoInitialize(void * reserved) //参数必须为NULLu 注意:对每一个进程,COM库函数只需要(xūyào)初始化一次,由于COM主要用于创建组件,进程内组件无需初始化COM库u在退出之前调用u void CoUninitialize(void * reserved)u 注意:和初始化函数配合使用u由于OLE建立在COM基础上,初始化需要(xūyào)调用OleInitialize() 函数和OleUnInitialize() 函数uDCOM使用CoInitializeEx函数进行初始化初始化函数初始化函数(hánshù)第38页/共84页第三十八页,共85页。

      关于关于(guānyú)HRESULTu组件组件API及接口指针及接口指针(zhǐzhēn)中,除了中,除了uIUnknown::AddRef()uIUnknown::Release()u两个函数外,其它所有的函数,都以两个函数外,其它所有的函数,都以 HRESULT 作为返回值作为返回值 uHRESULT 是一个双字节的值是一个双字节的值u最高位最高位0表示成功表示成功u最高位最高位1表示错误表示错误第39页/共84页第三十九页,共85页 uHRESULTuS_OK 0x00000000 成功uS_FALSE 0x00000001 函数成功执行完成,但返回时出错uE_INVALIDARG 0x80070057 参数有错误uE_OUTOFMEMORY 0x8007000E 内存申请错误uE_UNEXPECTED 0x8000FFFF 未知的异常uE_NOTIMPL 0x80004001 未实现功能uE_FAIL 0x80004005 没有详细说明的错误uE_POINTER 0x80004003 无效的指针uE_HANDLE 0x80070006 无效的句柄uE_ABORT 0x80004004 终止操作uE_ACCESSDENIED 0x80070005 访问被拒绝uE_NOINTERFACE 0x80004002 不支持(zhīchí)接口关于关于(guānyú)HRESULT第40页/共84页第四十页,共85页。

      u由于由于(yóuyú)注册表中包含的是注册表中包含的是CLSID的字符串表示,因此的字符串表示,因此需要一些函数完成需要一些函数完成CLSID与表示与表示CLSID的字符串之间的转换的字符串之间的转换u StringFromGUID2 :将将GUID转换为字符串类型转换为字符串类型u其它:其它:uStringFromCLSID :将:将CLSID转化为文本串转化为文本串uStringFromIID :将:将IID转化为文本串转化为文本串uCLSIDFromString :将一个文本串转化为:将一个文本串转化为CLSIDuIIDFromString :将一个文本串转化为:将一个文本串转化为IIDuIsEqualGUID/IsEqualIID/IsEqualCLSIDuCLSIDFromProgID与与GUID(CLSID)相关相关(xiāngguān)的函数的函数第41页/共84页第四十一页,共85页 对象创建对象创建(chuàngjiàn)函函数:数:CoGetClassObjectCoCreateInstanceCoCreateInstanceExCoRegisterClassObjectCoRevokeClassObjectCoDisconnectObject内存管理内存管理(guǎnlǐ)函数:函数:CoTaskMemAllocCoTaskMemReallocCoTaskMemFreeCoGetMalloc第42页/共84页第四十二页,共85页。

      一个一个(yī ɡè)例子:例子:IX * pIX = NULL;HRESULT hr = ::CoCreateInstance( CLSID_Component1,NULL,CLSCTX_INPROC_SERVER,IID_IDX,(void **) &pIX);if (SUCCEEDED(hr)) {pIX -> FX();pIX -> Release();}第43页/共84页第四十三页,共85页 Windows 注册注册表表u系统注册表是一个全操作系统范围公用的信息仓库,可用作客系统注册表是一个全操作系统范围公用的信息仓库,可用作客户程序、构件程序和户程序、构件程序和COM库三者交换有关库三者交换有关COM对象信息和接口对象信息和接口信息的场所信息的场所uWindows操作系统的系统注册表中包括硬件、软件、配置及用操作系统的系统注册表中包括硬件、软件、配置及用户等各种信息户等各种信息u由由REGEDIT.EXE启动启动u由由REGSVR32.EXE来注册某个构件来注册某个构件u系统注册表是一个由许多系统注册表是一个由许多(xǔduō)元素构成的层次结构,每个元素构成的层次结构,每个元素均被称作一个关键字,每个关键字可以包含一系列子关键字元素均被称作一个关键字,每个关键字可以包含一系列子关键字u例如:例如:HKEY_CLASSES_ROOTuCLSIDuProgID 等等第44页/共84页第四十四页,共85页。

      第45页/共84页第四十五页,共85页 第46页/共84页第四十六页,共85页 通过通过Windows 注册注册(zhùcè)表注册表注册(zhùcè)组件组件u注册注册(zhùcè)文件文件u REGEDIT4u [HKEY_CLASSES_ROOT\TEST]u @=“TESTCOM"u [HKEY_CLASSES_ROOT\TEST\CLSID]u @="{b91c46bc-5841-4f41-95f3-daade42b3436}"第47页/共84页第四十七页,共85页 组件注册其它组件注册其它(qítā)方法方法u情况情况1:当使用:当使用 ATL((Active Template Library)) 编写组件程序,编写组件程序,编译成功编译成功(chénggōng)后,后,IDE 自动完成注册;自动完成注册;u情况情况2:当使用:当使用 MFC 编写组件程序,由于编译器不知道编写的编写组件程序,由于编译器不知道编写的是否是是否是 COM 组件,所以无法自动注册可执行菜单组件,所以无法自动注册可执行菜单“Tools\Register Control”来注册来注册u情况情况3:当写了一个具有:当写了一个具有 COM 功能的功能的 EXE 程序时,运行一次程序时,运行一次该程序即可完成组件注册该程序即可完成组件注册u情况情况4:当需要使用第三方提供的组件程序时,可通过命令行运:当需要使用第三方提供的组件程序时,可通过命令行运行行“regsvr32.exe 文件名文件名”来注册来注册,反注册的方法是反注册的方法是“regsvr32.exe /u 文件名文件名”;; 第48页/共84页第四十八页,共85页。

      关于注册关于注册(zhùcè)组件组件u情况情况5:当需要在程序中(如安装程序)执行:当需要在程序中(如安装程序)执行(zhíxíng)注注册,那么:册,那么: u typedef HRESULT (WINAPI * FREG)(); u TCHAR szWorkPath[ MAX_PATH ]; u ::GetCurrentDirectory( sizeof(szWorkPath), szWorkPath ); u ::SetCurrentDirectory( 组件目录组件目录 ); u HMODULE hDLL = ::LoadLibrary( 组件文件名组件文件名 );u if(hDLL) { u FREG lpfunc = (FREG)::GetProcAddress( hDLL, _T("DllRegisterServer") ); u if ( lpfunc ) lpfunc(); u ::FreeLibrary(hDLL); u } u ::SetCurrentDirectory(szWorkPath);第49页/共84页第四十九页,共85页。

      u类工厂是能够创建其它类工厂是能够创建其它COM对象的特殊对象的特殊COM对象,类工厂支持对象,类工厂支持一个特殊的接口一个特殊的接口IClassFactory,为例化,为例化CoClass构件类提供了一构件类提供了一种标准机制种标准机制u每一个每一个COM对象类应该有一个相应对象类应该有一个相应(xiāngyīng)的类工厂对象的类工厂对象uIClassFactory接口中定义了两个重要的操作接口中定义了两个重要的操作uCreateInstance:生成生成COM对象并返回所请求接口的指针对象并返回所请求接口的指针uLockServer:负责在内存中保持:负责在内存中保持COM构件构件类工厂类工厂(gōngchǎng)第50页/共84页第五十页,共85页 u具有四个输入参数和一个输出参数:第一个参数表示待创建具有四个输入参数和一个输出参数:第一个参数表示待创建组件组件(zǔ jiàn)的的CLSID,第三个参数表示组件,第三个参数表示组件(zǔ jiàn)执行执行上下文,第四个参数表示待使用接口的上下文,第四个参数表示待使用接口的IID,输出代表接口指,输出代表接口指针针u执行上下文可通过如下值组合执行上下文可通过如下值组合u CLSCTX_INPROC_SERVER, CLSCTX_INPROC_HANDLER, CLSCTX_LOCAL_SERVER, CLSCTX_REMOTE_SERVERu无法为组件无法为组件(zǔ jiàn)的创建加上限制条件;用该函数建立组的创建加上限制条件;用该函数建立组件件(zǔ jiàn)后,无法控制组件后,无法控制组件(zǔ jiàn)的装载位置或无法检的装载位置或无法检查客户是否有权限创建该组件查客户是否有权限创建该组件(zǔ jiàn),,CoCreateInstances函数的灵活性不足函数的灵活性不足u有必要使用一个专门用于创建所需组件有必要使用一个专门用于创建所需组件(zǔ jiàn)的组件的组件(zǔ jiàn):类厂:类厂关于关于(guānyú)CoCreateInstance(guānyú)CoCreateInstance的分析的分析第51页/共84页第五十一页,共85页。

      类厂类厂(Class Factory)(Class Factory)u如果使用类厂,如果使用类厂,CoCreateInstance实际上未直接创建实际上未直接创建COM构件构件,而是创而是创建了一个被称为类厂的构件,类厂构件的唯一功能是创建其他构件建了一个被称为类厂的构件,类厂构件的唯一功能是创建其他构件u客户客户(kè hù)可以通过类厂所支持的接口来对类厂创建构件的过程加以可以通过类厂所支持的接口来对类厂创建构件的过程加以控制控制uCoCreateInstance首先调用首先调用CoGetClassObjec获取类厂中的获取类厂中的IClassFactory接口的指针接口的指针u然后使用返回的指针调用然后使用返回的指针调用IClassFactory::CreateInstance完成新组件的创完成新组件的创建建第52页/共84页第五十二页,共85页 IClassFactory:用于创建用于创建(chuàngjiàn)构件的标准接口构件的标准接口Interface IClassFactory: IUnknown{HRESULT _stdcallCreateInstance( IUnknown * pUnknownOuter,const IID & iid,void ** ppv );HRESULT _stdcall LockServer(BOOL block);}u另一个创建接口:IClassFactory2增加了许可和权限功能,通过使用该接口,类厂可以保证客户只能(zhī nénɡ)获得他能合法访问的组件,并具有此组件的访问授权第53页/共84页第五十三页,共85页。

      CoCreateInstance 通过通过(tōngguò) CoGetClassObject实现实现HRESULT CoCreateInstance (const CLSID& clsid,IUnknown * pUnknownOuter,DWOED dwClsContext,const IID& iid,void ** ppv){ *ppv = NULL; IClassFactory * pIFactory = NULL; HRESULT hr = CoGetClassObject(clsid, dwClsContext, NULL, IID_IClassFactory, (void)** &pIFactory); if (SUCCEEDED(hr)){hr=pIFactory->CreateInstance(pUnknownOuter, iid, ppv);pIFactory -> Release(); }return hr;}第54页/共84页第五十四页,共85页 组件组件(zǔ jiàn)(zǔ jiàn)创建过程创建过程客户COM库DLL类厂组件CoCreateInstanceCoGetClassObjectDllGetClassObjectNew CFactoryIClassFactory::CreateInstance(IID_IX)New CAIClassFactory::ReleasepIX->Fx()第55页/共84页第五十五页,共85页。

      u是指包含一个是指包含一个(yī ɡè)或多个或多个COM对象类和相应的类工厂,能向对象类和相应的类工厂,能向客户提供服务的一个客户提供服务的一个(yī ɡè)程序(程序(EXE)或库()或库(DLL))COM服务器服务器客户机 构件 类对象对象COM库系统注册表{CLSID} SERVER.DLL1.客户调用CoGetClassObject2.COM定位所请求的类对象3.构件被启动4.类对象创建成功后将IClassFactory接口指针经COM库返回给客户机5.客户调用IClassFactory创建实例7.接口将指针返回给客户机6.对象(duìxiàng)被创建第56页/共84页第五十六页,共85页 COM的复用的复用(fù yònɡ)方式方式uCOM不允许直接继承不允许直接继承(jìchéng),但可通过包含和聚合来代替,但可通过包含和聚合来代替继承继承(jìchéng)u如果一个构件如果一个构件B使用另外一个构件使用另外一个构件A,我们称使用者,我们称使用者B为外部为外部构件,被使用者构件,被使用者A为内部构件为内部构件, u 则称:外部构件则称:外部构件B包含(聚合)了内部构件包含(聚合)了内部构件Au包含与聚合是包含与聚合是COM的两种复用方式(模型),为系统升级和的两种复用方式(模型),为系统升级和扩展提供支持扩展提供支持第57页/共84页第五十七页,共85页。

      包含包含(bāohán)((Containment))对象对象A对象对象BIYIXIX’IUnknown第58页/共84页第五十八页,共85页 客户程序对象B对象A调用调用ISomeInterfaceISomeInterface包含包含(bāohán)((Containment))第59页/共84页第五十九页,共85页 u对象对象B的成员函数在调用对象的成员函数在调用对象A的接口之前或之后可以进行的接口之前或之后可以进行其他任何操作其他任何操作uIX’ 提供的功能可以超过提供的功能可以超过IXu对象对象B是对象是对象A的客户,而对象的客户,而对象B的客户看到的只是的客户看到的只是(zhǐshì)对象对象B显露出的接口(显露出的接口(IY和和IX’))u对象对象A的创建与释放完全在对象的创建与释放完全在对象B内部进行,对象内部进行,对象A的生命的生命期包含在对象期包含在对象B的生命期内的生命期内包含包含(bāohán)((Containment))第60页/共84页第六十页,共85页 聚合聚合(jùhé) (Aggregation)对象对象A对象对象BIYIXIUnknownIUnknown第61页/共84页第六十一页,共85页。

      聚合聚合(jùhé) (Aggregation)客户程序对象B对象A调用传递ISomeInterfaceIOtherInterface第62页/共84页第六十二页,共85页 u聚合可看作是包含聚合可看作是包含(bāohán)(bāohán)的一个特例,聚合更好地体现了复用的一个特例,聚合更好地体现了复用u虽然对象虽然对象A A直接向对象直接向对象B B的客户提供服务,但对象的客户提供服务,但对象B B的客户感觉不的客户感觉不到对象到对象A A的存在,对象的存在,对象A A的生存期受到对象的生存期受到对象B B的控制的控制u实现聚合的关键在于实现聚合的关键在于QueryInterfaceQueryInterfaceu当客户向对象当客户向对象B B请求请求IXIX时时, ,对象对象B B的的QueryInterfaceQueryInterface返回对象返回对象A A的的IXIX指针指针u存在问题:存在问题:u((1 1)从)从IXIX如何得到如何得到IYIY??u((2 2)从)从IXIX得到的得到的IunknownIunknown如何与从如何与从IYIY得到的得到的IUnknown IUnknown 相同?相同?聚合聚合(jùhé) (jùhé) (Aggregation)(Aggregation)第63页/共84页第六十三页,共85页。

      u包含的复用性建立在客户包含的复用性建立在客户/ /服务器模式上,而聚服务器模式上,而聚合的复用性需要内部构件提供支持合的复用性需要内部构件提供支持u复用方式的选择:复用方式的选择:u当内部构件提供的接口完全满足要求时,使用聚当内部构件提供的接口完全满足要求时,使用聚合合适合合适u当内部构件提供的接口与需求当内部构件提供的接口与需求(xūqiú)(xūqiú)类似时,类似时,使用包含合适使用包含合适u在一个对象中可以同时使用两种复用方式在一个对象中可以同时使用两种复用方式包含与聚合包含与聚合(jùhé)(jùhé)的使的使用用第64页/共84页第六十四页,共85页 u自动化是允许高级语言使用构件的自动化是允许高级语言使用构件的COM应用技术,自动化的应用技术,自动化的核心是核心是IDispatch接口,自动化对象就是实现了接口,自动化对象就是实现了IDispatch接口接口的的COM对象对象uIDispatch接口是自动化对象必须实现的接口接口是自动化对象必须实现的接口, IDispatch在在IUnkown接口的基础上增加了如下操作接口的基础上增加了如下操作uGetIDsOfNames 操作负责返回操作或属性及其参数名字操作负责返回操作或属性及其参数名字(míng zi)的分发标识符(分发的分发标识符(分发ID,即,即DISPID:用于管理属:用于管理属性和操作)性和操作)uGetTypeInfo 处理对象类型信息处理对象类型信息uGetTypeInfoCount 处理对象类型信息处理对象类型信息uInvoke 是是IDispatch的核心操作,根据分发的核心操作,根据分发ID执行相应函数执行相应函数COM的动态的动态(dòngtài)激活机制激活机制-自动化自动化第65页/共84页第六十五页,共85页。

      COM的动态激活的动态激活(jī huó)机制机制-自动化自动化构件构件客户机客户机IDispatch指针对象对象Vtable指针IDispatch VtableInvokeInvoke(DISP d,…) {Switch(d){Case 1: Method1();Case 2: Method2()Method2() {…}Method1() {…}第66页/共84页第六十六页,共85页 uInvoke操作和分发操作和分发ID机制使得运行时动态绑定属性和方法成机制使得运行时动态绑定属性和方法成为可能,但灵活性的代价是效率的降低如果将为可能,但灵活性的代价是效率的降低如果将DISP硬编码硬编码在应用中而不是频繁调用在应用中而不是频繁调用GetIDsofNames(即早绑定即早绑定),情况也,情况也许会更好,许会更好,IDL中用中用disinterface支持该类情况支持该类情况u对象描述语言对象描述语言ODL是对是对IDL的扩充,用来描述的扩充,用来描述COM对象的类对象的类型信息,包括接口的类型信息(型信息,包括接口的类型信息(interface或或disinterface)和)和COM对象类的类型信息(用对象类的类型信息(用coclass关键字描述)关键字描述)u类型库是类型库是IDL文件经过编译后产生的一个资源文件,包含文件经过编译后产生的一个资源文件,包含COM服务器中服务器中COM对象和接口的信息对象和接口的信息uIDL用用library描述类型库信息,包括类型库的全局描述类型库信息,包括类型库的全局(quánjú)唯唯一标识符(一标识符(LIBID)、类型库所使用的版本、语言等)、类型库所使用的版本、语言等COM的动态的动态(dòngtài)激活机制激活机制-自动化自动化第67页/共84页第六十七页,共85页。

      COM的动态的动态(dòngtài)激活机制激活机制-自动化自动化u自动化组件可以被脚本语言直接调用自动化组件可以被脚本语言直接调用(diàoyòng),也称为双接,也称为双接口组件口组件第68页/共84页第六十八页,共85页 uDCOM是是COM的进一步扩展,的进一步扩展,DCOM用网络协议来代替本地用网络协议来代替本地(běndì)进程之间的通信,并针对分布环境提供了一些新的特性,例进程之间的通信,并针对分布环境提供了一些新的特性,例如:位置透明、网络安全性、跨平台调用等如:位置透明、网络安全性、跨平台调用等uDCOM的分布特性依靠远程过程调用实现的分布特性依靠远程过程调用实现分布构件对象分布构件对象(duìxiàng)模型模型DCOM客户机COM运行时环境安全提供者 DCE RPC协议栈COM运行时环境安全提供者 DCE RPC协议栈构件DCOM网络协议第69页/共84页第六十九页,共85页 u基于基于COM组件开发可简要描述为以下几个过程组件开发可简要描述为以下几个过程u建立建立COM组件组件u基于基于ATL编程编程u基于基于MFC编程(可用于实现自动化组件)编程(可用于实现自动化组件)u组件的编译组件的编译(biānyì)u组件的注册组件的注册u编写客户端程序,调用组件的接口函数编写客户端程序,调用组件的接口函数基于基于COM组件组件(zǔ jiàn)的开发的开发过程过程第70页/共84页第七十页,共85页。

      组件程序组件程序(chéngxù)的的编译编译第71页/共84页第七十一页,共85页 u说明说明1:编译后,类型库以:编译后,类型库以 TLB 文件形式单独存在,同时也保存在目文件形式单独存在,同时也保存在目标文件的资源中标文件的资源中 #import 引入类型库的时候,既可以指定引入类型库的时候,既可以指定 TLB 文文件,也可以指定目标文件件,也可以指定目标文件u说明说明2::IDL 编译后生成编译后生成(shēnɡ chénɡ)代理代理/存根源程序,有:存根源程序,有:u dlldata.c、、xxx_p.c、、xxxps.def、、xxxps.maku 可以用可以用 NMAKE.EXE 再次编译来产生真正的代理再次编译来产生真正的代理/存根存根DLL目标目标文件文件 组件程序编译组件程序编译(biānyì)过程过程 第72页/共84页第七十二页,共85页 u组件调用的方法主要分为以下几种组件调用的方法主要分为以下几种:u#include方法方法:IDL编译编译(biānyì)后,会产生后,会产生xxx.h和和xxx_i.c文文件可直接件可直接#include该文件该文件,如如:u #include “ComTest.h"u #include “ComTest_i.c“u 如用到如用到CComBSTR,还需要包含还需要包含:#include u#import方法方法:比较通用的方法,比较通用的方法,vc 会帮我们产生包装类会帮我们产生包装类,如如:u #import “ComTest.tlb“客户端程序客户端程序-组件组件(zǔ jiàn)调用调用 第73页/共84页第七十三页,共85页。

      #include "ComTest.h"#include "ComTest_i.c" ::CoInitialize( NULL ); IUnknown * pUnk = NULL; IFun * pFun = NULL; HRESULT hr; hr = ::CoCreateInstance(CLSID_Fun,NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (LPVOID *) &pUnk); if( FAILED( hr ) )throw( _T(“组件(zǔ jiàn)没注册!") ); hr = pUnk->QueryInterface(IID_IFun,(LPVOID *)&pFun ); if( FAILED( hr ) )throw( _T("没有接口?") ); hr = pFun->Add( 1, 2, &nSum ); //调用组件(zǔ jiàn)函数组件调用组件调用(diàoyòng)-简单调用简单调用(diàoyòng)1 第74页/共84页第七十四页,共85页。

      #include "ComTest.h"#include "ComTest_i.c" ::CoInitialize( NULL ); IFun * pFun = NULL; HRESULT hr; hr = ::CoCreateInstance(CLSID_Fun,NULL, CLSCTX_INPROC_SERVER,IID_IUnknown, (LPVOID *) & pFun ); if( FAILED( hr ) )throw( _T(“组件没注册或 没有(méi yǒu)接口!") ); hr = pFun->Add( 1, 2, &nSum ); //调用组件函数 ::CoUninitialize();组件组件(zǔ jiàn)调用调用-简单调用简单调用2 第75页/共84页第七十五页,共85页 #include "ComTest.h"#include "ComTest_i.c“ ::CoInitialize( NULL ); CComPtr < IUnknown > spUnk; CComPtr < IFun > spFun; HRESULT hr; hr = spUnk.CoCreateInstance( CLSID_Fun ); if( FAILED( hr ) )throw( _T("没注册组件") ); hr = spUnk.QueryInterface( &spFun ); if( FAILED( hr ) )throw( _T("没有(méi yǒu)接口") ); hr = spFun->Add( 1, 2, &nSum );组件组件(zǔ jiàn)调用调用-指针调用指针调用1第76页/共84页第七十六页,共85页。

      #include "ComTest.h"#include "ComTest_i.c" CComPtr < IUnknown > spUnk;// 定义 IUnknown 的智能指针 CComQiPtr < IFun > spFun;// 定义 IFun 的智能指针 HRESULT hr; hr = spUnk.CoCreateInstance( L“ComTest.Fun.1" ); if( FAILED( hr ) )throw( _T("没注册(zhùcè)组件") ); spFun = spUnk; if(!spFun)throw( _T("没有接口") ); hr = spFun->Add( 1, 2, &nSum );组件调用组件调用(diàoyòng)-指针调用指针调用(diàoyòng)2第77页/共84页第七十七页,共85页 #include "ComSimple.h"#include "ComSimple_i.c" CComQIPtr < IFun, &IID_IFun > spFun;// 定义 IFun 的智能(zhì nénɡ)指针 HRESULT hr; hr = spFun.CoCreateInstance( L"Simple1.fun.1" ); if(!spFun)throw( _T("没有接口") ); hr = spFun->Add( 1, 2, &nSum );组件组件(zǔ jiàn)调用调用-指针调用指针调用3第78页/共84页第七十八页,共85页。

      自动化组件自动化组件(zǔ jiàn)的开发的开发u利用(lìyòng)MFC实现u必须注册,调用Tools\Register control 完成u编写客户端程序,实现调用第79页/共84页第七十九页,共85页 自动化组件自动化组件(zǔ jiàn)的使用方式的使用方式u使用使用Api方式调用方式调用u CLSID clsid; // 通过通过 ProgID 得到得到(dé dào) CLSIDu HRESULT hr = ::CLSIDFromProgID( L"ComTestA.DispCom", &clsid );u IDispatch * pDisp = NULL;u hr = ::CoCreateInstance( clsid, NULL, CLSCTX_ALL, IID_IDispatch, (LPVOID *)&pDisp );u LPOLESTR pwFunName = L"Add";// 准备取得准备取得 Add 函数的序函数的序号号u DISPID dispID;u hr = pDisp->GetIDsOfNames(IID_NULL,&pwFunName,1,LOCALE_SYSTEM_DEFAULT,&dispID );u VARIANTARG v[2];u v[0].vt = VT_I4; v[0].lVal = 2;v[1].vt = VT_I4;v[1].lVal = 1;u DISPPARAMS dispParams = { v, NULL, 2, 0 };u VARIANT vResult;u hr = pDisp->Invoke(dispID,IID_NULL,DISPATCH_METHOD,u&dispParams,&vResult,NULL,NULL);第80页/共84页第八十页,共85页。

      自动化组件自动化组件(zǔ jiàn)的使用方式的使用方式u使用使用 CComDispatchDriver 的智能指针包装类调用的智能指针包装类调用u CLSID clsid; // 通过通过 ProgID 取得组件取得组件(zǔ jiàn)的的CLSID u HRESULT hr = ::CLSIDFromProgID( u L“ComSampe6.Fun.1", &clsid ); u CComPtr < IUnknown > spUnk; u hr = ::CoCreateInstance( clsid, NULL, CLSCTX_ALL,u IID_IUnknown, (LPVOID *)&spUnk ); uCComDispatchDriver spFun( spUnk ); uCComVariant v1(1), v2(2), vResult; // 参数参数 u hr = spDisp.Invoke2(L"Add", &v1, &v2, &vResult);第81页/共84页第八十一页,共85页。

      自动化组件的使用自动化组件的使用(shǐyòng)方式方式u使用使用 MFC 装载类型库的包装方式调用装载类型库的包装方式调用u建立一个建立一个 MFC 的应用程序的应用程序 u开启开启(kāiqǐ) ClassWizard,执行,执行 Add Class,选择,选择 From a type libraryu选择类型库中需要包装的接口选择类型库中需要包装的接口u编写调用代码编写调用代码u IFun spFun; u spFun.CreateDispatch( _T(“ComSampe6.Fun.1") ) u long nSum = spFun.Add(4,2);u spDisp.ReleaseDispatch(); 第82页/共84页第八十二页,共85页 思考题思考题l什么是什么是COM/DCOM/COM+COM/DCOM/COM+??lCOMCOM规范规范(guīfàn)(guīfàn)是指什么是指什么??l什么是什么是COMCOM实现?实现?第83页/共84页第八十三页,共85页 谢谢您的观看(guānkàn)!第84页/共84页第八十四页,共85页。

      内容(nèiróng)总结主要内容COM定义了客户与构件之间互操作的标准,包括规约与实现两个部分当下列条件中的任何一个变化时,应给新接口指定新IID使用QueryInterface查询某个构件是否(shì fǒu)支持某个特定的接口COM不允许直接继承,但可通过包含和聚合来代替继承聚合可看作是包含的一个特例,聚合更好地体现了复用include “ComTest_i.c“import “ComTest.tlb“谢谢您的观看第八十五页,共85页。

      点击阅读更多内容
      关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
      手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
      ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.