为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

高级软件工程06(COM基础:接口与实现)

2010-10-21 50页 ppt 153KB 22阅读

用户头像

is_082674

暂无简介

举报
高级软件工程06(COM基础:接口与实现)nullnull构件对象模型:COMnull 内 容 基础部分 综述 接口 实现 高级部分 包含与聚合 COM与VC 自动化 DCOM null(1) COM的起源 源于OLE: Object Link and Embedding OLE1 采用DDE(Dynamic Data Exchange) 在不同的程序之间进行通信 DDE缺点: 效率低,稳定性不好,使用不方便 COM是为克服上述不足而出现的 OLE2 以 ...
高级软件工程06(COM基础:接口与实现)
nullnull构件对象模型:COMnull 内 容 基础部分 综述 接口 实现 高级部分 包含与聚合 COM与VC 自动化 DCOM null(1) COM的起源 源于OLE: Object Link and Embedding OLE1 采用DDE(Dynamic Data Exchange) 在不同的程序之间进行通信 DDE缺点: 效率低,稳定性不好,使用不方便 COM是为克服上述不足而出现的 OLE2 以 COM 为基础 但OLE未能体现COM优点 1 综述COM基础null(2)什么是COM 构件对象模型:Component Object Model 客户与构件为了能够互操作而遵循的标准 COM标准包括与实现两部分 规范部分定义了构件之间的通信机制 这些规范不依赖于任何特定的语言 和操作系统 实现部分即COM库 为COM规范的具体实现提供一些核心服务 COM基础null(3) COM构件以 DLL或EXE形式发布的代码与语言无关 以二进制形式发布 可以在不妨碍客户的形式下被升级 可以透明地在网络上被重新分配 构件与类:一个构件可以由多个类实现 接口与类:一个类可以实现多个接口COM基础null(4) COM库 (COM Library) 功能: (1)实现客户方与服务器方COM应用的创建过程 (2)COM通过注册查找本地服务器(即EXE程序) 以及程序名与CLSID的转换 (3)提供标准的内存控制 DCOM的实现提供了分布式环境下的通信机制 在操作系统层次 以DLL文件的形式存在 COM基础null(5) COM特性 语言无关性 为跨语言合作开发提供了统一标准 并得到不同集成开发环境的支持 进程透明性 进程内服务程序: DLL 本地服务程序: EXE 远地服务程序: DLL或EXE 实现进程透明性的关键是COM库 它负责服务体的定位 管理对象的创建及对象与客户之间的通信 复用性 包含方式 聚合方式COM基础null(6) COM发展趋势 操作系统 成为系统的基本软件模型 数据库 OLE DB/ADO 以 COM 的方式 为数据访问提供一致的接口 Internet ActiveX包含了所有基于COM的Internet相关技术 COM+ 增加MTS等服务COM基础null2 COM接口COM接口是COM规范的核心内容 接口的意义(略) 一个接口包含了一组函数 在C++中, 可以用抽象基类来定义COM接口 接口的实现 : vtbl 指针 虚拟函数表COM基础nullVtbl指针虚拟函数表pIX接口的内存结构IX&Fx1&Fx2&Fx3&Fx4COM基础nullVtbl的作用:提高接口实现的灵活性例子:一个实现接口IX的类CA,CA包含2个数据:Vtbl指针虚拟函数表IX&Fx1&Fx2&Fx3&Fx4Data1Data2pAFx1 Fx2 Fx3 Fx4CACOM基础null两个实例 共享同一Vtbl:Vtbl指针虚拟函数表&Fx1&Fx2&Fx3&Fx4Data1Data2pA1 pA2Fx1 Fx2 Fx3 Fx4CAVtbl指针Data1Data2COM基础null 接口特点 实现级 二进制,独立于编程语言 稳定性 客户与服务器依赖于接口 继承性 便于扩展接口, 不提倡继承 所有接口皆继承Iunknown) 多态性:COM基础null(1)功能 提供: 生存期控制 接口查询 IUnknown的定义(IDL): interface IUnkown { virtual HRESULT QueryInterface( const IID&, void **ppv) = 0; virtual ULONG AddRef() = 0; virtual ULONG Release() = 0; } IUnknownCOM基础nullVtbl指针虚拟函数表IXQueryInterfaceAddRefRelease&FxpAQueryInterface AddRef Release FxCA所有接口都必须继承IUnknownCOM基础nullIUnknown指针的获取 IUnknown * CreateInstance(); 创建构件时,客户可以使用CreateInstance, 而不是new。 CreateInstance的定义: IUnknown * CreateInstance() { IUnknown * pI = static_cast (new foo); pI -> AddRef(); return pI; } COM基础null(2)引用计数 AddRef与Release 控制构件的生命期 解决内存管理问题 使构件能够自己将自己删除 使用规则 返回接口指针之前调用 AddRef; 使用完接口之后调用Release; 赋值之后调用AddRef;COM基础null引用计数的实现方式: 在什么层次上进行计数 构件 对象 接口构件构件引用记数对象引用记数对象引用记数对象1对象2接口接口接口接口接口引用记数接口引用记数接口引用记数接口引用记数COM基础null(3)接口查询一个COM对象(构件)可以实现多个接口 使用QueryInterface查询某个构件是否支持某个特定的接口 QueryInterface的使用 void foo(Iunknown * pI){ //Define a pointer for the interface. IX * pIX = NULL; //Ask for nterface IX HRESULT hr = pI->QueryUbterface(IID_IX, (void **)&pIX); //Check return value. If (SUCCEEDED(hr)) { // Use interface pIX->Fx(); } }COM基础nullQueryInterface的实现 假定存在类 CA,继承接口 IX 与 IY: HRESULT _sfdcall CA:: QueryInterface(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; } static_cast(*ppv)->AddRef(); return S_OK; }COM基础nullQueryInterface的实现规则QueryInterface返回的总是同一个IUnknown指针 若客户曾经获取过某个接口,那么它将总能获取此接口 客户可以再次获取已经拥有的接口 客户可以返回到起始接口 若能够从某个接口获取某特定接口 则可以从(该构件的)任意接口获取此接口COM基础null 新版本构件的处理COM接口永远不会变化 :一个IID就是一个接口 通过发行新版本构件解决兼容性 当下列条件中的任何一个变化时 应给新接口指定新IID: 接口中函数数目 接口中函数顺序 某个函数的参数 某个函数参数的顺序 某个函数参数的类型 函数可能的返回值 函数返回值的类型 等 不同版本接口的命名:在老名称后加一个数字 COM基础null3 COM实现(1)预备知识: DLL DLL是一个构件服务器 EXE也可以是构件服务器 使用户在应用程序的运行过程中替换构件 构件是DLL中实现的接口集 DLL共享它们所链入的应用程序地址空间 HRESULT 向用户报告构件运行结果状况 “Here is the RESULT” WINERROR.H中进行定义 用户可以定义自己的代码COM基础nullGUID:Globally Unique IDentifier用于标识构件(CLSID)与接口(IID) 128位(长整数) 由于空间足够大 接口标识冲突较小 可以用编程的方法生成具有唯一性的GUID VC: UUIDGEN.EXE, GUIDGEN.EXE 借鉴了OSF的UUID(DCE中的RPC使用). 对GUID值的传递通常通过引用进行COM基础CLSID:CLaSs IDentifiernullWindows 注册表Windows操作系统的共享系统数据库 包括 硬件 软件 配置及用户等各种信息 由 REGEDIT.EXE (95/98) REGEDIT32.EXE(NT) 启动 可以使用REGSVR32.EXE来注册某个构件 注册表是一个由许多元素构成的层次结构 每一个元素均被称作是一个关键字 每一个关键字可以包含一系列子关键字等 例如: HKEY_CLASSES_ROOT CLSID ProgID 等COM基础nullCOM基础nullCOM基础null(2)COM库COM构件与客户皆需要完成的相同操作 由OLE32.DLL、OLE32.LIB实现 COM库中常用的函数: 初始化函数 与GUID相关的函数 对象创建函数 内存管理函数COM基础null 在使用COM库中的其他函数(除CoBuildVersion) 之前,进程必须先调用: HRESULT CoInitialize(void * reserved) 在退出之前调用: void CoUninitialize(void * reserved) 其他: CoBuildVersion CoFreeUnusedLibraries OleInitialize建立在CoInitialize基础之上 DCOM使用CoInitializeEx初始化函数:COM基础null与GUID(CLSID)相关的函数: 例如:将GUID转换为一个字符串: wchar_t szCLSID[39]; int r = :: StringFromGUID2(CLSID_Component1, szCLSID, 39); 其它: StringFromCLSID StringFromIID CLSIDFromString IIDFromString IsEqualGUID IsEqualIID IsEqualCLSID CLSIDFromProgIDCOM基础null对象创建函数:CoGetClassObject CoCreateInstance CoCreateInstanceEx CoRegisterClassObject CoRevokeClassObject CoDisconnectObject内存管理函数:CoTaskMemAlloc CoTaskMemRealloc CoTaskMemFree CoGerMallocCOM基础null(3) 类厂(Class Factory)能够创建其他构件的构件 (构件厂) 其本身也是一个COM对象 支持一个特殊的接口 IClassFacroty 每一个COM对象类应该有一个相应的类厂对象COM基础nullCoCreateInstance COM库函数之一 HRESULT_stdcall CoCreateInstance( const CLSID& clsid, Iunkown * pIUnknownOuter, DWORD dwClsContext, const IID& iid, void ** ppv ); clsid:待创建构件的标识; pIUnknownOuter:用于聚合; dwClsContext:限定所创建构件的上下文; iid:构件上待使用接口的标识; ppv:所返回接口的指针。COM基础null一个使用例子: IX * pIX = NULL; HRESULT he = ::CoCreateInstance( CLSID_Component1, NULL, CLSCTX_INPROC_SERVER, IID_IDX, (void **) &pIX); if (SUCCEEDED(hr)) { pIX -> FX(); pIX -> Release(); }COM基础null类厂CoCreateInstance实际上 未直接创建COM构件 创建了一个被称为类厂的构件 类厂构件的唯一功能是创建其他构件 客户可以通过类厂所支持的接口来 对类厂创建 构件的过程加以控制 CoCreateInstance调用CoGetClassObject 创建构件的标准接口是IClassFactoryCOM基础nullCoGetClassObject 创建类厂HRESULT_stdcall CoGetClassObject( const CLSID& clsid, DWORD dwClsContext, COSERVERINFO * pServerInfo,//用于DCOM const IID& iid, void ** ppv //指向类厂中某个接口的指针 ); COM基础nullIClassFactory 用于创建构件的标准接口Interface IClassFactory: IUnknown { HRESULT _stdcall CreateInstance( IUnknown * pUnknownOuter, const IID & iid, void ** ppv ); HRESULT _stdcall LockServer(BOOL block); }未接收CLSID:只能创建同某个CLSID相应的构件IClassFactory2COM基础nullCoCreateInstance 与 CoGetClassObject的关系: 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); if (SUCCEEDED(hr)){ hr=pIFactory->CreateInstance(pUnknownOuter, iid, ppv); pIFactory -> Release(); } return hr; }COM基础null在下列情况下应直接使用CoGetClassObject 而应使用CoCreateInstance: (1)如果希望用不同于IClassFactory的某个创建接口 来创建构件 例如 IClassFactory2 (2)如果希望创建同一构件的多个实例 COM基础 null(4)类厂的实现 CoGetClassObject需要DLL中的一个特定的函数 来创建构件的类厂 DllGetClassObject: STDAPI DllGetClassObject( const CLSID& clsid, const IID& iid, void ** ppv ); COM基础null创建、调用构件的过程:客户COM库DLLCoGetClassObject调用CoGetClassObjectDllGetClassObjectIClassFactoryIXpIClassFactorypIXCOM基础创建类厂创建构件返回IClassFactory调用IClassFactory::CreateInstance返回IX调用IX::Fxnull#include #include #include "Iface.h" int 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->QueryInterface(IID_IY, (void**)&pIY) ; if (SUCCEEDED(hr)){ pIY->Fy() ; // Use interface IY. pIY->Release() ; }客户方代码COM基础(5)例子null IZ* pIZ = NULL ; hr = pIX->QueryInterface(IID_IZ, (void**)&pIZ) ; if (SUCCEEDED(hr)){ pIZ->Fz() ; pIZ->Release() ; } pIX->Release() ; } else { cout << "Client: \t\tCould not create component. hr = " << hex << hr << endl ; } // Uninitialize COM Library CoUninitialize() ; return 0 ; }COM基础null#include #include #include "Iface.h" // Interface declarations #include "Registry.h" // Registry helper functions static HMODULE g_hModule = NULL ; // DLL module handle static long g_cComponents = 0 ; // Count of active components static long g_cServerLocks = 0 ; // Count of locks // Friendly name of component const char g_szFriendlyName[] = "Inside COM, Ch 7 Example" ; // Version-independent ProgID const char g_szVerIndProgID[] = "InsideCOM.Chap07" ;服务器方代码COM基础nullclass CA : public IX, public IY { public: // IUnknown virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ; virtual ULONG __stdcall AddRef() ; virtual ULONG __stdcall Release() ; // Interface IX virtual void __stdcall Fx() { cout << "Fx" << endl ;} // Interface IY virtual void __stdcall Fy() { cout << "Fy" << endl ;} // Constructor CA() ; // Destructor ~CA() ; private: // Reference count long m_cRef ; } ;COM基础nullHRESULT __stdcall CA::QueryInterface(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 ; }COM基础nullclass CFactory : public IClassFactory{ public: // IUnknown virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ; virtual ULONG __stdcall AddRef() ; virtual ULONG __stdcall Release() ; // Interface IClassFactory virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) ; virtual HRESULT __stdcall LockServer(BOOL bLock) ; // Constructor CFactory() : m_cRef(1) {} // Destructor ~CFactory() {} private: long m_cRef ; } ;COM基础nullHRESULT __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 ; } reinterpret_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 ; }COM基础null// IClassFactory implementation HRESULT __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) ; // Release the IUnknown pointer. // (If QueryInterface failed, component will delete itself.) pA->Release() ; return hr ; } COM基础null// LockServer HRESULT __stdcall CFactory::LockServer(BOOL bLock) { if (bLock){ InterlockedIncrement(&g_cServerLocks) ; } else{ InterlockedDecrement(&g_cServerLocks) ;} return S_OK ; } STDAPI DllCanUnloadNow() { if ((g_cComponents == 0) && (g_cServerLocks == 0)){ return S_OK ;} else{ return S_FALSE ;} }COM基础nullSTDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv){ if (clsid != CLSID_Component1) return CLASS_E_CLASSNOTAVAILABLE ;} CFactory* pFactory = new CFactory ; if (pFactory == NULL){ return E_OUTOFMEMORY ;} HRESULT hr = pFactory->QueryInterface(iid, ppv) ; pFactory->Release() ; return hr ; } COM基础nullSTDAPI DllRegisterServer(){ return RegisterServer(g_hModule, CLSID_Component1, g_szFriendlyName, g_szVerIndProgID, g_szProgID) ; } STDAPI DllUnregisterServer() { return UnregisterServer(CLSID_Component1, g_szVerIndProgID, g_szProgID) ; }COM基础nullBOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { g_hModule = hModule ; } return TRUE ; }COM基础nullclientCOM LibDLLCFactoryCApIX->Fx()New CANew CFactoryIClassFactory::ReleaseIClassFactory::CreateInstance(IID_IX)CoGetClassObjectDllGetClassObjectCOM基础
/
本文档为【高级软件工程06(COM基础:接口与实现)】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索