




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1构件对象模型构件对象模型:COM高级软件工程2基础部分基础部分综述综述接口接口实现实现高级部分高级部分包含与聚合包含与聚合COM与与VC自动化自动化DCOM高级软件工程3(1) COM的起源的起源 源于源于OLE: Object Link and Embedding OLE1 采用采用DDE(Dynamic Data Exchange) 在不同的程序之间进行通信在不同的程序之间进行通信DDE缺点缺点: 效率低效率低,稳定性不好稳定性不好,使用不方便使用不方便 COM是为克服上述不足而出现的是为克服上述不足而出现的 OLE2 以以 COM 为基础为基础 但但OLE未能体现未能体现COM优点优点
2、 1 综述综述4(2)什么是什么是COM 构件对象模型构件对象模型:Component Object Model 客户与构件为了能够互操作而遵循的标准客户与构件为了能够互操作而遵循的标准 COM标准包括规范与实现两部分标准包括规范与实现两部分规范部分定义了构件之间的通信机制规范部分定义了构件之间的通信机制这些规范不依赖于任何特定的语言这些规范不依赖于任何特定的语言和操作系统和操作系统实现部分即实现部分即COM库库为为COM规范的具体实现提供一些核心服务规范的具体实现提供一些核心服务高级软件工程5(3) COM构件构件以以 DLL或或EXE形式发布的代码形式发布的代码与语言无关与语言无关以二进制
3、形式发布以二进制形式发布可以在不妨碍客户的形式下被升级可以在不妨碍客户的形式下被升级可以透明地在网络上被重新分配可以透明地在网络上被重新分配构件与类构件与类:一个构件可以由多个类实现一个构件可以由多个类实现接口与类接口与类:一个类可以实现多个接口一个类可以实现多个接口6(4) COM库库 (COM Library)功能功能: (1)实现客户方与服务器方实现客户方与服务器方COM应用的创建过程应用的创建过程(2)COM通过注册表查找本地服务器通过注册表查找本地服务器(即即EXE程序程序) 以及程序名与以及程序名与CLSID的转换的转换(3)提供标准的内存控制方法提供标准的内存控制方法DCOM的实
4、现提供了分布式环境下的通信机制的实现提供了分布式环境下的通信机制在操作系统层次在操作系统层次 以以DLL文件的形式存在文件的形式存在高级软件工程7(5) COM特性特性语言无关性语言无关性为跨语言合作开发提供了统一标准为跨语言合作开发提供了统一标准并得到不同集成开发环境的支持并得到不同集成开发环境的支持 进程透明性进程透明性进程内服务程序进程内服务程序: DLL本地服务程序本地服务程序: EXE远地服务程序远地服务程序: DLL或或EXE实现进程透明性的关键是实现进程透明性的关键是COM库库它负责服务体的定位它负责服务体的定位 管理对象的创建及对象与客户之间的通信管理对象的创建及对象与客户之间
5、的通信复用性复用性包含方式包含方式 聚合方式聚合方式8(6) COM发展趋势发展趋势操作系统操作系统 成为系统的基本软件模型成为系统的基本软件模型数据库数据库 OLE DB/ADO 以以 COM 的方式的方式为数据访问提供一致的接口为数据访问提供一致的接口Internet ActiveX包含了所有基于包含了所有基于COM的的Internet相关技术相关技术COM+增加增加MTS等服务等服务高级软件工程92 COM接口接口COM接口是接口是COM规范的核心内容规范的核心内容接口的意义接口的意义(略略)一个接口包含了一组函数一个接口包含了一组函数在在C+中中, 可以用抽象基类来定义可以用抽象基类来
6、定义COM接口接口接口的实现接口的实现 : vtbl 指针指针 虚拟函数表虚拟函数表10Vtbl指针指针虚拟函数表虚拟函数表pIX接口的内存结构接口的内存结构IX&Fx1&Fx2&Fx3&Fx4高级软件工程11Vtbl的作用的作用:提高接口实现的灵活性提高接口实现的灵活性例子例子:一个实现接口一个实现接口IX的类的类CA,CA包含包含2个数据个数据:Vtbl指针指针虚拟函数表虚拟函数表IX&Fx1&Fx2&Fx3&Fx4Data1Data2pAFx1Fx2Fx3Fx4CA12两个实例两个实例 共享同一共享同一Vtbl:Vtbl指针指针虚拟函数表虚拟函数表&Fx1&Fx2&Fx3&Fx4Data
7、1Data2pA1pA2Fx1Fx2Fx3Fx4CAVtbl指针指针Data1Data2高级软件工程13 接口特点接口特点实现级实现级二进制,独立于编程语言二进制,独立于编程语言稳定性稳定性客户与服务器依赖于接口客户与服务器依赖于接口继承性继承性便于扩展接口便于扩展接口, 不提倡继承不提倡继承所有接口皆继承所有接口皆继承Iunknown)多态性:多态性:14(1)功能)功能提供:提供:生存期控制生存期控制接口查询接口查询 IUnknown的定义(的定义(IDL):):interface IUnkownvirtual HRESULT QueryInterface(const IID&, void
8、 *ppv) = 0;virtual ULONG AddRef() = 0;virtual ULONG Release() = 0;高级软件工程15Vtbl指针指针虚拟函数表虚拟函数表IXQueryInterfaceAddRefRelease&FxpAQueryInterfaceAddRefReleaseFxCA所有接口都必须继承所有接口都必须继承IUnknown16IUnknown指针的获取指针的获取 IUnknown * CreateInstance();创建构件时,客户可以使用创建构件时,客户可以使用CreateInstance, 而不是而不是new。CreateInstance的定义:
9、的定义: IUnknown * CreateInstance() IUnknown * pI = static_cast (new foo); pI - AddRef(); return pI; 高级软件工程17AddRef与与Release控制构件的生命期控制构件的生命期解决内存管理问题解决内存管理问题使构件能够自己将自己删除使构件能够自己将自己删除使用规则使用规则返回接口指针之前调用返回接口指针之前调用 AddRef;使用完接口之后调用使用完接口之后调用Release;赋值之后调用赋值之后调用AddRef;18引用计数的实现方式引用计数的实现方式:在什么层次上进行计数在什么层次上进行计数构
10、件构件对象对象接口接口构件构件构件引用记数构件引用记数对象引用记数对象引用记数对象引用记数对象引用记数对象对象1对象对象2接口接口接口接口接口接口接口接口接口引用记数接口引用记数接口引用记数接口引用记数接口引用记数接口引用记数接口引用记数接口引用记数高级软件工程19一个一个COM对象(构件)可以实现多个接口对象(构件)可以实现多个接口使用使用QueryInterface查询某个构件是否支持某个特定的接口查询某个构件是否支持某个特定的接口 void foo(Iunknown * pI)/Define a pointer for the interface.IX * pIX = NULL;/Ask
11、 for nterface IXHRESULT hr = pI-QueryUbterface(IID_IX, (void *)&pIX);/Check return value.If (SUCCEEDED(hr) / Use interfacepIX-Fx();20 假定存在类假定存在类 CA,继承接口继承接口 IX 与与 IY: HRESULT _sfdcall CA: QueryInterface(const IID& iid, void * ppv) if (iid = IID_IUnknown) *ppv = static_cast(this); else if (iid = IID_
12、IX) *ppv = static_cast(this); else if (iid = IID_IY) *ppv = static_cast(this);else *ppv = NULL; return E_NOINTERFACE;static_cast(*ppv)-AddRef();return S_OK;高级软件工程21QueryInterface返回的总是同一个返回的总是同一个IUnknown指针指针若客户曾经获取过某个接口若客户曾经获取过某个接口,那么它将总能获取此接口那么它将总能获取此接口客户可以再次获取已经拥有的接口客户可以再次获取已经拥有的接口客户可以返回到起始接口客户可以返回
13、到起始接口若能够从某个接口获取某特定接口若能够从某个接口获取某特定接口则可以从则可以从(该构件的该构件的)任意接口获取此接口任意接口获取此接口22COM接口永远不会变化接口永远不会变化 :一个一个IID就是一个接口就是一个接口 通过发行新版本构件解决兼容性通过发行新版本构件解决兼容性当下列条件中的任何一个变化时当下列条件中的任何一个变化时应给新接口指定新应给新接口指定新IID:接口中函数数目接口中函数数目接口中函数顺序接口中函数顺序某个函数的参数某个函数的参数某个函数参数的顺序某个函数参数的顺序某个函数参数的类型某个函数参数的类型函数可能的返回值函数可能的返回值函数返回值的类型函数返回值的类型
14、等等不同版本接口的命名不同版本接口的命名:在老名称后加一个数字在老名称后加一个数字23(1)预备知识预备知识:DLLDLL是一个构件服务器是一个构件服务器EXE也可以是构件服务器也可以是构件服务器使用户在应用程序的运行过程中替换构件使用户在应用程序的运行过程中替换构件构件是构件是DLL中实现的接口集中实现的接口集DLL共享它们所链入的应用程序地址空间共享它们所链入的应用程序地址空间HRESULT向用户报告构件运行结果状况向用户报告构件运行结果状况“Here is the RESULT”WINERROR.H中进行定义中进行定义用户可以定义自己的代码用户可以定义自己的代码24GUID: Globa
15、lly Unique IDentifier用于标识构件用于标识构件(CLSID)与接口与接口(IID)128位位(长整数长整数)由于空间足够大由于空间足够大 接口标识冲突较小接口标识冲突较小可以用编程的方法生成具有唯一性的可以用编程的方法生成具有唯一性的GUIDVC: UUIDGEN.EXE, GUIDGEN.EXE借鉴了借鉴了OSF的的UUID(DCE中的中的RPC使用使用).对对GUID值的传递通常通过引用进行值的传递通常通过引用进行CLSID:CLaSs IDentifier25Windows 注册表注册表Windows操作系统的共享系统数据库操作系统的共享系统数据库包括包括 硬件硬件
16、软件软件 配置及用户等各种信息配置及用户等各种信息由由REGEDIT.EXE (95/98) REGEDIT32.EXE(NT) 启动启动可以使用可以使用REGSVR32.EXE来注册某个构件来注册某个构件注册表是一个由许多元素构成的层次结构注册表是一个由许多元素构成的层次结构每一个元素均被称作是一个关键字每一个元素均被称作是一个关键字每一个关键字可以包含一系列子关键字等每一个关键字可以包含一系列子关键字等 例如:例如:HKEY_CLASSES_ROOTCLSIDProgID 等等262728(2)COM库库COM构件与客户皆需要完成的相同操作构件与客户皆需要完成的相同操作由由OLE32.DL
17、L、OLE32.LIB实现实现COM库中常用的函数:库中常用的函数:初始化函数初始化函数与与GUID相关的函数相关的函数对象创建函数对象创建函数内存管理函数内存管理函数29 在使用在使用COM库中的其他函数(除库中的其他函数(除CoBuildVersion)之前,进程必须先调用:之前,进程必须先调用:HRESULT CoInitialize(void * reserved) 在退出之前调用:在退出之前调用:void CoUninitialize(void * reserved) 其他:其他:CoBuildVersionCoFreeUnusedLibraries OleInitialize建立在
18、建立在CoInitialize基础之上基础之上 DCOM使用使用CoInitializeEx初始化函数:初始化函数:30与与GUID(CLSID)相关的函数:相关的函数:例如:将例如:将GUID转换为一个字符串:转换为一个字符串:wchar_t szCLSID39;int r = : StringFromGUID2(CLSID_Component1, szCLSID, 39);其它:其它:StringFromCLSIDStringFromIIDCLSIDFromStringIIDFromStringIsEqualGUIDIsEqualIIDIsEqualCLSIDCLSIDFromProgID
19、31对象创建函数:对象创建函数:CoGetClassObjectCoCreateInstanceCoCreateInstanceExCoRegisterClassObjectCoRevokeClassObjectCoDisconnectObject内存管理函数:内存管理函数:CoTaskMemAllocCoTaskMemReallocCoTaskMemFreeCoGerMalloc32能够创建其他构件的构件能够创建其他构件的构件(构件厂构件厂)其本身也是一个其本身也是一个COM对象对象支持一个特殊的接口支持一个特殊的接口 IClassFacroty每一个每一个COM对象类应该有一个相应的类厂对
20、象对象类应该有一个相应的类厂对象33CoCreateInstanceCOM库函数之一库函数之一HRESULT_stdcall CoCreateInstance(const CLSID& clsid,Iunkown * pIUnknownOuter,DWORD dwClsContext,const IID& iid,void * ppv);clsid:待创建构件的标识;待创建构件的标识;pIUnknownOuter:用于聚合;:用于聚合;dwClsContext:限定所创建构件的上下文;:限定所创建构件的上下文;iid:构件上待使用接口的标识;:构件上待使用接口的标识;ppv:所返回接口的指针。
21、:所返回接口的指针。34一个使用例子:一个使用例子:IX * pIX = NULL;HRESULT he = :CoCreateInstance( CLSID_Component1,NULL,CLSCTX_INPROC_SERVER,IID_IDX,(void *) &pIX);if (SUCCEEDED(hr) pIX - FX();pIX - Release();35类厂类厂CoCreateInstance实际上实际上未直接创建未直接创建COM构件构件创建了一个被称为类厂的构件创建了一个被称为类厂的构件类厂构件的唯一功能是创建其他构件类厂构件的唯一功能是创建其他构件客户可以通过类厂所支持的
22、接口来客户可以通过类厂所支持的接口来对类厂创建对类厂创建构件的过程加以控制构件的过程加以控制CoCreateInstance调用调用CoGetClassObject创建构件的标准接口是创建构件的标准接口是IClassFactory36CoGetClassObject创建类厂创建类厂HRESULT_stdcall CoGetClassObject(const CLSID& clsid,DWORD dwClsContext,COSERVERINFO * pServerInfo,/用于用于DCOMconst IID& iid,void * ppv /指向类厂中某个接口的指针指向类厂中某个接口的指针)
23、;37IClassFactory 用于创建构件的标准接口用于创建构件的标准接口Interface IClassFactory: IUnknownHRESULT _stdcallCreateInstance( IUnknown * pUnknownOuter,const IID & iid,void * ppv );HRESULT _stdcall LockServer(BOOL block);未接收未接收CLSID:只能创建同某个:只能创建同某个CLSID相应的构件相应的构件IClassFactory238CoCreateInstance 与与 CoGetClassObject的关系:的关系:
24、CoCreateInstance 通过通过 CoGetClassObject实现实现HRESULT CoCreateInstance(const CLSID& clsid,IUnknown * pUnknownDuter,DWOED dwClsContext,const IID& iid,void * ppv) * ppv = NULL;IClassFactory * pIFactory = NULL;HRESULT hr = CoGetClassObject(clsid, dwClsContext, NULL, IID_IClassFactory, (void)* &pIFactory);i
25、f (SUCCEEDED(hr)hr=pIFactory-CreateInstance(pUnknownOuter, iid, ppv);pIFactory - Release();return hr;39在下列情况下应直接使用在下列情况下应直接使用CoGetClassObject 而应使用而应使用CoCreateInstance:(1)如果希望用不同于如果希望用不同于IClassFactory的某个创建接口的某个创建接口来创建构件来创建构件 例如例如 IClassFactory2(2)如果希望创建同一构件的多个实例如果希望创建同一构件的多个实例40(4)类厂的实现)类厂的实现CoGetCla
26、ssObject需要需要DLL中的一个特定的函数中的一个特定的函数来创建构件的类厂来创建构件的类厂DllGetClassObject:STDAPI DllGetClassObject(const CLSID& clsid,const IID& iid,void * ppv);41创建、调用构件的过程:创建、调用构件的过程:客户客户COM库库DLLCoGetClassObject调用调用CoGetClassObjectDllGetClassObjectIClassFactoryIXpIClassFactorypIX创建类厂创建类厂创建构件创建构件返回返回IClassFactory调用调用ICla
27、ssFactory:CreateInstance返回返回IX调用调用IX:Fx42#include #include #include Iface.hint main()CoInitialize(NULL) ;IX* pIX = NULL ; HRESULT hr = :CoCreateInstance(CLSID_Component1,NULL, CLSCTX_INPROC_SERVER, IID_IX, (void*)&pIX) ;if (SUCCEEDED(hr)pIX-Fx() ; / Use interface IX.IY* pIY = NULL ;hr = pIX-QueryInt
28、erface(IID_IY, (void*)&pIY) ;if (SUCCEEDED(hr)pIY-Fy() ; / Use interface IY.pIY-Release() ;客户方代码客户方代码(5)例子)例子43IZ* pIZ = NULL ;hr = pIX-QueryInterface(IID_IZ, (void*)&pIZ) ;if (SUCCEEDED(hr)pIZ-Fz() ;pIZ-Release() ;pIX-Release() ;elsecout Client: ttCould not create component. hr = hex hr endl ; / Un
29、initialize COM LibraryCoUninitialize() ;return 0 ;44#include #include #include Iface.h / Interface declarations#include Registry.h / Registry helper functionsstatic HMODULE g_hModule = NULL ; / DLL module handlestatic long g_cComponents = 0 ; / Count of active componentsstatic long g_cServerLocks =
30、0 ; / Count of locks/ Friendly name of componentconst char g_szFriendlyName = Inside COM, Ch 7 Example ;/ Version-independent ProgIDconst char g_szVerIndProgID = InsideCOM.Chap07 ;服务器方代码服务器方代码45class CA : public IX, public IY public:/ IUnknownvirtual HRESULT _stdcall QueryInterface(const IID& iid, v
31、oid* ppv) ;virtual ULONG _stdcall AddRef() ;virtual ULONG _stdcall Release() ;/ Interface IXvirtual void _stdcall Fx() cout Fx endl ;/ Interface IYvirtual void _stdcall Fy() cout Fy endl ; / ConstructorCA() ;/ DestructorCA() ;private:/ Reference countlong m_cRef ; ;46HRESULT _stdcall CA:QueryInterfa
32、ce(const IID& iid, void* ppv)if (iid = IID_IUnknown)*ppv = static_cast(this) ; else if (iid = IID_IX)*ppv = static_cast(this) ;else if (iid = IID_IY)*ppv = static_cast(this) ; else*ppv = NULL ;return E_NOINTERFACE ;reinterpret_cast(*ppv)-AddRef() ;return S_OK ;47class CFactory : public IClassFactory
33、public:/ IUnknownvirtual HRESULT _stdcall QueryInterface(const IID& iid, void* ppv) ; virtual ULONG _stdcall AddRef() ;virtual ULONG _stdcall Release() ;/ Interface IClassFactoryvirtual HRESULT _stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void* ppv) ;virtual HRESULT _stdcall Lock
34、Server(BOOL bLock) ; / ConstructorCFactory() : m_cRef(1) / DestructorCFactory() private:long m_cRef ; ;48HRESULT _stdcall CFactory:QueryInterface(const IID& iid, void* ppv)if (iid = IID_IUnknown) | (iid = IID_IClassFactory)*ppv = static_cast(this) ; else *ppv = NULL ;return E_NOINTERFACE ;reinterpre
35、t_cast(*ppv)-AddRef() ;return S_OK ;ULONG _stdcall CFactory:AddRef()return InterlockedIncrement(&m_cRef) ;ULONG _stdcall CFactory:Release() if (InterlockedDecrement(&m_cRef) = 0)delete this ;return 0 ;return m_cRef ;49/ IClassFactory implementationHRESULT _stdcall CFactory:CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void* ppv) if (pUnknownOuter != NULL)return CLASS_E_NOAGGREGATION ;CA* pA = new CA ;if (pA = NULL)return E_OUTOFMEMORY ;HRESULT hr = pA-QueryInterface(iid, ppv) ;/ Rele
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 IEC 62282-7-2:2025 RLV EN Fuel cell technologies - Part 7-2: Test methods - Single cell and stack performance tests for solid oxide fuel cells (SOFCs)
- 【正版授权】 IEC TS 61400-28:2025 EN Wind energy generation systems - Part 28: Through-life management and life extension of wind power assets
- 【正版授权】 IEC 61558-1:1997+AMD1:1998 CSV FR-D Safety of power transformers,power supply units and similar - Part 1: General requirements and tests
- 滴滴代驾行业培训
- 2025年个人农机工作方案
- 2025年世界卫生日活动策划方案
- 2025年乡政府个人工作方案
- 2025年社区方案生育年终总结
- 产妇膳食营养课件
- 2025年幼儿园小班班务工作方案参考
- 校长接待日登记表
- 西班牙社会与文化智慧树知到课后章节答案2023年下天津外国语大学
- 2021上海慢行交通规划设计导则
- 望京SOHO中心工程标准化实施汇报图文详细
- 人工全髋关节置换术演示文稿
- 经颅多普勒超声在脑血管疾病中的应用及临床价值研究
- 变压器比率差动保护的校验方法(图文)
- 高盛Marquee平台深度研究报告
- CPR1000核电系统简介
- 05价值观探索-职业生涯规划
- TSEESA 010-2022 零碳园区创建与评价技术规范
评论
0/150
提交评论