




已阅读5页,还剩79页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
哈尔滨工业大学计算机学院唐好选Email:tanghx,COM技术及组件开发,主要内容,COM的基本原理构件对象模型COM/DCOM基于COM构件的开发,COM是微软提出的第一个构件模型,源于OLE:ObjectLinkandEmbedding(动态链接和嵌入)OLE1采用DDE(DynamicDataExchange:动态数据交换)在不同的程序之间进行通信DDE缺点:建立在Windows消息机制基础上,效率低、稳定性不好、使用不方便COM是为克服上述不足而出现的,COM技术的发展,COM定义了客户与构件之间互操作的标准,包括规约与实现两个部分规约部分定义了构件之间的通信机制,这些规约不依赖于任何特定的语言和操作系统实现部分就是COM库,为COM规约的具体实现提供了一些核心服务COM仅支持同一台计算机上(当然是Windows操作系统)的互操作,不支持分布式计算环境,COM技术的发展,将COM技术延伸到分布计算环境,产生了所谓的DCOM(DistributedCOM,分布构件对象模型)用网络协议代替本地进程之间的通信针对分布环境提供了新特性:位置透明网络安全性跨平台调用等为了满足企业级应用的需求,推出了微软事务服务器(MTS:MicrosoftTransactionServer),把应用系统的客户程序、应用构件和各种资源有机结合起来,为分布式企业应用提供了一种服务器端的构件运行和部署环境,COM技术的发展,为了使Windows真正成为企业应用平台,微软推出了分布式网络应用体系结构(WindowsDNA:DistributedinterNetApplicationArchitecture),DNA是一个完整的、多层的企业应用体系结构:包含工具、数据库、操作系统、编程模型和应用服务等随着Windows2000的发布,微软进一步把COM、DCOM、MTS统一起来,形成了真正适合于企业级应用的构件技术:COM+可以认为:COM/DCOM+MTS=COM+COM+是一种中间件技术规约,提供操作系统级的分布式“服务”,COM技术的发展,WindowDNA,是一个服务器端的开发平台,包括WindowsNT/2000/2003提供运行环境和支持COM/DCOMMSMQ消息队列产品,支持构件间异步通信MTS管理构件的应用服务MicrosoftWolfpack支持集群服务器的软件MicrosoftSQLServerMicrosoftIISWeb服务器MicrosoftManagementConsole部署和管理工具,WindowDNA,COM+基本结构,COM+目录负载平衡驻留内存数据库对象池新的事件模型构件管理和部署JIT激活,COM+,MTS事务支持资源分发管理安全模型易于管理,远程支持DCOM分布式构件服务,COM基于接口的编程模型基本的构件服务,COM(ComponentObjectModel),组件对象模型,是一种以组件为发布单元的对象模型,这种模型使得各个软件组件可以用一种统一的方式进行交互COM是一种协议,它建立了一个软件模块同另一个软件模块之间的连接,提供了组件之间进行交互的规范,也提供了实现交互的环境当这种连接建立起来后,两个模块之间就可以通过“接口”的机制来进行通讯,这些接口既不需要静态的或动态的连接入口点,也不需要编码很复杂的地址,什么是COM?,全局唯一标识符(GlobalUniqueIDentifier)来源于OSF的通用统一标识符UUID(UniversalUniqueIDentifier),是一个128位整数用于标识COM对象(CLSID)和接口(IID)由于空间足够大,冲突较小.可以用编程的方法生成具有唯一性的GUIDVC:UUIDGEN.EXE,GUIDGEN.EXE对GUID值的传递通常通过引用进行,COM基本概念:GUID,基本概念:COM对象/COM构件/COM接口,基本概念:COM对象和COM构件,在COM规约中,“构件”和“对象”经常混淆,所谓COM对象是指符合COM规则的CoClass(构件类)的实例,每一个COM对象都有一个GUID,称为CLSID(CoClassID)COM构件是指以编译后的形式提供一组功能的COM对象独立于具体编程语言一个构件可以由多个类实现以二进制形式(DLL或EXE)发布可以在不妨碍客户的形式下被升级可以透明地在网络上被重新分配,COM接口是COM规范的核心内容,是COM对象显示出来的所有信息,是一组逻辑上相关的函数集合每一个接口都有一个GUID,称为接口标识符(简称IID:InterfaceIDentifier)COM接口具有不变性,只允许单继承一个COM对象可以实现多个接口,这体现了COM对象的多态性,这些接口由IUnknown接口来管理在C+中,可以用抽象基类来定义COM接口,基本概念:COM接口,新版本构件的处理,COM接口永远不会变化:一个IID就是一个接口,当对组件进行升级时,一般不会修改已有的接口,而是加入一些新接口当下列条件中的任何一个变化时,应给新接口指定新IID接口中函数数目接口中函数顺序某个函数的参数某个函数参数的顺序某个函数参数的类型函数可能的返回值函数返回值的类型等不同版本接口的命名:在老名称后加一个数字,是所有COM对象都必须实现的接口,其它接口都直接或间接继承IUnknown(IID为00000000-0000-0000-C000-000000000046)接口,包含三个基本操作AddRef:提供生存周期管理功能,增加对象引用计数Release:提供生存周期管理功能,用于释放对象QueryInterface:负责向客户提供接口查询功能,基本概念:IUnknown接口,IUknown接口的定义,定义在win32SDK中的UNKNWN.h头文件中:interfaceIUnkownvirtualHRESULT_stdcallQueryInterface(constIID,微软接口定义语言MIDL(MicrosoftInterfaceDefinitionLanguage)是定义COM接口的申述式语言通过独立于具体编程语言的方式来定义接口该语言基于OSF分布式计算环境(DCE)远程过程调用(RPC)的接口描述语言IDLCOM规范使用的IDL接口描述语言不仅可用于COM接口,同时还定义了一些常用的数据类型,也可描述自定义的数据结构,对于接口的成员函数,可以指定每个参数的类型、输入输出特性,甚至可支持变长度的数组的描述MIDL支持指针类型,与C/C+类似,基本概念:接口定义语言,接口定义例:interfaceIDictionaryHRESULTInitialize();HRESULTLoadLibrary(instring);HRESULTInsertWord(instring,instring);HRESULTDeleteWord(instring);HRESULTLookWorld(instring,outstring*);HRESULTRestoreLibrary(instring);HRESULTFreeLibrary();,基本概念:接口定义语言,COM接口是一个二进制标准,客户同接口的连接并不是通过其名称或其成员函数的名称来实现的,而是通过其在内存块中的位置完成的COM接口是一个包含一个函数指针数组的内存结构,每一个数组元素包含的是一个由组件所实现的函数的地址C+通过纯抽象基类实现COM接口,实际上是定义了一个内存块的结构,但此内存只是在派生类中实现此抽象基类时才会被分配,派生类继承此抽象基类时将继承此内存结构,COM接口,虚拟函数表,COM接口的内存结构同C+编译器为抽象基类所生成的内存结构是相同的,对于如下利用纯抽象基类方式定义的接口interfaceIXvirtualvoid_stdcallFx1()=0;virtualvoid_stdcallFx2()=0;virtualvoid_stdcallFx3()=0;virtualvoid_stdcallFx4()=0;,提高接口实现的灵活性,实现抽象基类的类可能会将特定于实例的信息同vtbl一块保存,例子:一个实现接口IX的类CA,CA包含2个数据:classCA:publicIXpublic:virtualvoid_stdcallFx1()virtualvoid_stdcallFx2()virtualvoid_stdcallFx3()virtualvoid_stdcallFx4()doubleData1;doubleData2;,Vtbl的作用,Vtbl指针,虚拟函数表,IX,创建构件时,客户可以使用CreateInstance,而不是newCreateInstance的定义:IUnknown*CreateInstance()IUnknown*pI=static_cast(newfoo);pI-AddRef();returnpI;,IUnknown指针的获取,一个COM对象(构件)可以实现多个接口.使用QueryInterface查询某个构件是否支持某个特定的接口voidfoo(Iunknown*pI)IX*pIX=NULL;HRESULThr=pI-QueryInterface(IID_IX,(void*),接口查询,假定存在类CA,继承接口IX与IYHRESULT_stdcallCA:QueryInterface(constIID,QueryInterface的实现,QueryInterface返回的总是同一个IUnknown指针若客户曾经获取过某个接口,那么它将总能获取此接口客户可以再次获取已经拥有的接口客户可以返回到起始接口若能够从某个接口获取某特定接口,则可以从(该构件的)任意接口获取此接口,QueryInterface的实现规则,通过函数AddRef与Release实现控制构件的生命期解决内存管理问题使构件能够自己将自己删除使用规则返回接口指针之前调用AddRef;使用完接口之后调用Release;赋值之后调用AddRef;,引用计数,在什么层次上进行计数:构件?对象?接口?,引用计数的实现方式,函数的参数中使用接口指针变量对于输入参数,被调函数不必改变计数对于输出参数,相当于生成了一个新的接口指针变量,因此在返回之前,需要使计数增1对于输入输出参数,参数修改之前计数减1,修改之后计数加1,若参数未被修改,计数不变对于局部接口指针变量,不改变计数对于全局接口指针变量,作为参数传给某函数之前,计数增1,返回之后计数减1,C+类成员变量为接口指针变量时也采用此规则,引用计数的更详细的规则,COM构件可以和客户机程序在同一个进程中,也可以在不同的进程中前者称为进程内构件(INPROC_SERVER)后者称为进程外构件(LOCAL_SERVER)如果是DCOM,进程外构件还包括CLSCTX_REMOTE_SERVER,COM构件与客户机之间的通信机制,在Windows平台上,进程内构件以动态链接库(DLL)形式实现由于DLL包含一个导出函数表,客户机程序和DLL动态连接时会建立一张表,把客户机调用和DLL中函数的地址连接起来因此客户机程序和进程内构件可通过直接函数调用进行交互进程内构件程序也可称作进程内服务程序,COM构件与客户机之间的通信机制,对于进程外构件,由于进程之间相互屏蔽,客户机进程不能直接调用构件进程,需要遵循操作系统对进程间通信所做的规定,在Windows平台上,进程外构件以EXE实现,COM采用本地过程调用(LPC)作为进程间通信机制,COM构件与客户机之间的通信机制,当调用组件的时候,其实是依靠代理(运行在本地)和存根(运行在远端)之间的通讯完成的,组件调用机制,COM不仅定义了客户与构件之间交互的规约,而且提供了全面的实现细节,COM的实现与操作系统密切相关,包括:COM库(COMLibrary)系统注册表(windowsregistry)类工厂COM服务器,COM的实现,是COM标准的系统级实现,为COM对象的标识和创建、内存管理、构件程序的卸载等提供了一组标准接口和辅助函数在Windows系统中,COM库主要包含在OLE32.dll、OLE32.lib和RPCSS.dll文件中COM库很多地方直接用到了Windows系统的一些特性,例如系统注册表和动态链接库,COM通过注册表查找本地服务器(即EXE程序)以及程序名与CLSID的转换,COM库,COM库,COM库中常用的函数初始化函数与GUID相关的函数对象创建函数内存管理函数,在使用COM库中的其他函数之前,进程必须先调用HRESULTCoInitialize(void*reserved)/参数必须为NULL注意:对每一个进程,COM库函数只需要初始化一次,由于COM主要用于创建组件,进程内组件无需初始化COM库在退出之前调用voidCoUninitialize(void*reserved)注意:和初始化函数配合使用由于OLE建立在COM基础上,初始化需要调用OleInitialize()函数和OleUnInitialize()函数DCOM使用CoInitializeEx函数进行初始化,初始化函数,关于HRESULT,组件API及接口指针中,除了IUnknown:AddRef()IUnknown:Release()两个函数外,其它所有的函数,都以HRESULT作为返回值HRESULT是一个双字节的值最高位0表示成功最高位1表示错误,HRESULTS_OK0 x00000000成功S_FALSE0 x00000001函数成功执行完成,但返回时出错E_INVALIDARG0 x80070057参数有错误E_OUTOFMEMORY0 x8007000E内存申请错误E_UNEXPECTED0 x8000FFFF未知的异常E_NOTIMPL0 x80004001未实现功能E_FAIL0 x80004005没有详细说明的错误E_POINTER0 x80004003无效的指针E_HANDLE0 x80070006无效的句柄E_ABORT0 x80004004终止操作E_ACCESSDENIED0 x80070005访问被拒绝E_NOINTERFACE0 x80004002不支持接口,关于HRESULT,由于注册表中包含的是CLSID的字符串表示,因此需要一些函数完成CLSID与表示CLSID的字符串之间的转换StringFromGUID2:将GUID转换为字符串类型其它:StringFromCLSID:将CLSID转化为文本串StringFromIID:将IID转化为文本串CLSIDFromString:将一个文本串转化为CLSIDIIDFromString:将一个文本串转化为IIDIsEqualGUID/IsEqualIID/IsEqualCLSIDCLSIDFromProgID,与GUID(CLSID)相关的函数,对象创建函数:,CoGetClassObjectCoCreateInstanceCoCreateInstanceExCoRegisterClassObjectCoRevokeClassObjectCoDisconnectObject,内存管理函数:,CoTaskMemAllocCoTaskMemReallocCoTaskMemFreeCoGetMalloc,一个例子:IX*pIX=NULL;HRESULThr=:CoCreateInstance(CLSID_Component1,NULL,CLSCTX_INPROC_SERVER,IID_IDX,(void*),Windows注册表,系统注册表是一个全操作系统范围公用的信息仓库,可用作客户程序、构件程序和COM库三者交换有关COM对象信息和接口信息的场所Windows操作系统的系统注册表中包括硬件、软件、配置及用户等各种信息由REGEDIT.EXE启动由REGSVR32.EXE来注册某个构件系统注册表是一个由许多元素构成的层次结构,每个元素均被称作一个关键字,每个关键字可以包含一系列子关键字例如:HKEY_CLASSES_ROOTCLSIDProgID等,通过Windows注册表注册组件,注册文件REGEDIT4HKEY_CLASSES_ROOTTEST=“TESTCOMHKEY_CLASSES_ROOTTESTCLSID=b91c46bc-5841-4f41-95f3-daade42b3436,组件注册其它方法,情况1:当使用ATL(ActiveTemplateLibrary)编写组件程序,编译成功后,IDE自动完成注册;情况2:当使用MFC编写组件程序,由于编译器不知道编写的是否是COM组件,所以无法自动注册。可执行菜单“ToolsRegisterControl”来注册情况3:当写了一个具有COM功能的EXE程序时,运行一次该程序即可完成组件注册情况4:当需要使用第三方提供的组件程序时,可通过命令行运行“regsvr32.exe文件名”来注册,反注册的方法是“regsvr32.exe/u文件名”;,关于注册组件,情况5:当需要在程序中(如安装程序)执行注册,那么:typedefHRESULT(WINAPI*FREG)();TCHARszWorkPathMAX_PATH;:GetCurrentDirectory(sizeof(szWorkPath),szWorkPath);:SetCurrentDirectory(组件目录);HMODULEhDLL=:LoadLibrary(组件文件名);if(hDLL)FREGlpfunc=(FREG):GetProcAddress(hDLL,_T(DllRegisterServer);if(lpfunc)lpfunc();:FreeLibrary(hDLL);:SetCurrentDirectory(szWorkPath);,类工厂是能够创建其它COM对象的特殊COM对象,类工厂支持一个特殊的接口IClassFactory,为例化CoClass构件类提供了一种标准机制每一个COM对象类应该有一个相应的类工厂对象IClassFactory接口中定义了两个重要的操作CreateInstance:生成COM对象并返回所请求接口的指针LockServer:负责在内存中保持COM构件,类工厂,具有四个输入参数和一个输出参数:第一个参数表示待创建组件的CLSID,第三个参数表示组件执行上下文,第四个参数表示待使用接口的IID,输出代表接口指针执行上下文可通过如下值组合CLSCTX_INPROC_SERVER,CLSCTX_INPROC_HANDLER,CLSCTX_LOCAL_SERVER,CLSCTX_REMOTE_SERVER无法为组件的创建加上限制条件;用该函数建立组件后,无法控制组件的装载位置或无法检查客户是否有权限创建该组件,CoCreateInstances函数的灵活性不足有必要使用一个专门用于创建所需组件的组件:类厂,关于CoCreateInstance的分析,类厂(ClassFactory),如果使用类厂,CoCreateInstance实际上未直接创建COM构件,而是创建了一个被称为类厂的构件,类厂构件的唯一功能是创建其他构件客户可以通过类厂所支持的接口来对类厂创建构件的过程加以控制CoCreateInstance首先调用CoGetClassObjec获取类厂中的IClassFactory接口的指针然后使用返回的指针调用IClassFactory:CreateInstance完成新组件的创建,IClassFactory:用于创建构件的标准接口,InterfaceIClassFactory:IUnknownHRESULT_stdcallCreateInstance(IUnknown*pUnknownOuter,constIID,另一个创建接口:IClassFactory2增加了许可和权限功能,通过使用该接口,类厂可以保证客户只能获得他能合法访问的组件,并具有此组件的访问授权,CoCreateInstance通过CoGetClassObject实现HRESULTCoCreateInstance(constCLSID,组件创建过程,是指包含一个或多个COM对象类和相应的类工厂,能向客户提供服务的一个程序(EXE)或库(DLL),COM服务器,客户机,COM库,6.对象被创建,COM的复用方式,COM不允许直接继承,但可通过包含和聚合来代替继承如果一个构件B使用另外一个构件A,我们称使用者B为外部构件,被使用者A为内部构件,则称:外部构件B包含(聚合)了内部构件A包含与聚合是COM的两种复用方式(模型),为系统升级和扩展提供支持,包含(Containment),包含(Containment),对象B的成员函数在调用对象A的接口之前或之后可以进行其他任何操作IX提供的功能可以超过IX对象B是对象A的客户,而对象B的客户看到的只是对象B显露出的接口(IY和IX)对象A的创建与释放完全在对象B内部进行,对象A的生命期包含在对象B的生命期内,包含(Containment),聚合(Aggregation),聚合(Aggregation),聚合可看作是包含的一个特例,聚合更好地体现了复用虽然对象A直接向对象B的客户提供服务,但对象B的客户感觉不到对象A的存在,对象A的生存期受到对象B的控制实现聚合的关键在于QueryInterface当客户向对象B请求IX时,对象B的QueryInterface返回对象A的IX指针存在问题:(1)从IX如何得到IY?(2)从IX得到的Iunknown如何与从IY得到的IUnknown相同?,聚合(Aggregation),包含的复用性建立在客户/服务器模式上,而聚合的复用性需要内部构件提供支持复用方式的选择:当内部构件提供的接口完全满足要求时,使用聚合合适当内部构件提供的接口与需求类似时,使用包含合适在一个对象中可以同时使用两种复用方式,包含与聚合的使用,自动化是允许高级语言使用构件的COM应用技术,自动化的核心是IDispatch接口,自动化对象就是实现了IDispatch接口的COM对象IDispatch接口是自动化对象必须实现的接口,IDispatch在IUnkown接口的基础上增加了如下操作GetIDsOfNames操作负责返回操作或属性及其参数名字的分发标识符(分发ID,即DISPID:用于管理属性和操作)GetTypeInfo处理对象类型信息GetTypeInfoCount处理对象类型信息Invoke是IDispatch的核心操作,根据分发ID执行相应函数,COM的动态激活机制-自动化,COM的动态激活机制-自动化,Invoke操作和分发ID机制使得运行时动态绑定属性和方法成为可能,但灵活性的代价是效率的降低。如果将DISP硬编码在应用中而不是频繁调用GetIDsofNames(即早绑定),情况也许会更好,IDL中用disinterface支持该类情况对象描述语言ODL是对IDL的扩充,用来描述COM对象的类型信息,包括接口的类型信息(interface或disinterface)和COM对象类的类型信息(用coclass关键字描述)类型库是IDL文件经过编译后产生的一个资源文件,包含COM服务器中COM对象和接口的信息IDL用library描述类型库信息,包括类型库的全局唯一标识符(LIBID)、类型库所使用的版本、语言等,COM的动态激活机制-自动化,COM的动态激活机制-自动化,自动化组件可以被脚本语言直接调用,也称为双接口组件,DCOM是COM的进一步扩展,DCOM用网络协议来代替本地进程之间的通信,并针对分布环境提供了一些新的特性,例如:位置透明、网络安全性、跨平台调用等DCOM的分布特性依靠远程过程调用实现,分布构件对象模型DCOM,基于COM组件开发可简要描述为以下几个过程建立COM组件基于ATL编程基于MFC编程(可用于实现自动化组件)组件的编译组件的注册编写客户端程序,调用组件的接口函数,基于COM组件的开发过程,组件程序的编译,说明1:编译后,类型库以TLB文件形式单独存在,同时也保存在目标文件的资源中。#import引入类型库的时候,既可以指定TLB文件,也可以指定目标文件说明2:IDL编译后生成代理/存根源程序,有:dlldata.c、xxx_p.c、xxxps.def、xxxps.mak可以用NMAKE.EXE再次编译来产生真正的代理/存根DLL目标文件,组件程序编译过程,组件调用的方法主要分为以下几种:#include方法:IDL编译后,会产生xxx.h和xxx_i.c文件。可直接#include该文件,如:#include“ComTest.h#include“ComTest_i.c“如用到CComBSTR,还需要包含:#include#import方法:比较通用的方法,vc会帮我们产生包装类,如:#import“ComTest.tlb“,客户端程序-组件调用,#includeComTest.h#includeComTest_i.c:CoInitialize(NULL);IUnknown*pUnk=NULL;IFun*pFun=NULL;HRESULThr;hr=:CoCreateInstance(CLSID_Fun,NULL,CLSCTX_INPROC_SERVER,IID_IUnknown,(LPVOID*)/调用组件函数,组件调用-简单调用1,#includeComTest.h#includeComTest_i.c:CoInitialize(NULL);IFun*pFun=NULL;HRESULThr;hr=:CoCreateInstance(CL
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025ABB电动升降服务车
- 平行缝焊机行业分析:光电器件是最大的下游领域占有33%份额
- 房地产行业中期策略:企稳中谋转型
- 社群经济赋能女性跨境出海可持续发展白皮书
- 2025年食品冷链物流温控技术与冷链物流企业员工培训体系报告
- 2025年互联网医疗平台在线问诊平台与医疗机构合作案例研究报告
- 电商行业2025年知识产权保护与网络版权保护法律咨询报告
- 普惠金融背景下2025年金融科技应用对农村金融服务能力提升报告
- 钢铁产业绿色转型路径与2025年产能优化布局分析报告
- 农村土地流转规范化管理对农业生产效率提升报告
- 2024年济南综保控股集团有限公司招聘笔试冲刺题(带答案解析)
- JBT 2231.3-2011 往复活塞压缩机零部件 第3部分:薄壁轴瓦
- 2024-2030年中国果酱行业市场规模调研及前景趋势预测报告
- 2024中车大连机车车辆限公司招聘高校毕业生170人高频考题难、易错点模拟试题(共500题)附带答案详解
- 2023年中移动家庭网关终端技术规范
- 2024年湖南省公安厅机关警务辅助人员招聘笔试参考题库附带答案详解
- 2021年4月自考03200预防医学二试题及答案含解析
- (新版)光伏产业技能竞赛理论试题库及答案(浓缩500题)
- 青春期的妇科知识讲座
- 中考语文二轮专题复习《诗歌赏析之情感把握复习》公开课一等奖创新教学设计
- 2023起重机械安全技术规程
评论
0/150
提交评论