现在的位置: 首页 > 综合 > 正文

COM学习….

2013年04月17日 ⁄ 综合 ⁄ 共 4427字 ⁄ 字号 评论关闭
文章目录

COM初始化

if (CoInitialize(NULL) != S_OK)

{return 1;}

CoUninitialize();

COM库的内存管理

由于COM组件与客户程序,COM库三者之间内存交互(分配和释放可能不在同一个模块),所以必须使用一致的内在管理器。
COM提供的内在管理器标准:
class IMalloc:public IUnknow
{
    void*    Alloc(ULONG cb) = 0;
    void*    Realloc(void *pv, ULONG cb) = 0;
    void*    Free(void *pv) = 0;
    ULONG  GetSize(void *pv) = 0;
    int       DidAlloc(void *pv) = 0;
    void     HeapMinimize() = 0;
}

ANSI与UNICODE字符转换:
#include <comutil.h>
#pragma comment(lib, "comsuppw.lib")

namespace _com_util
{

char* __stdcall ConvertBSTRToString(
BSTR pSrc

BSTR __stdcall ConvertStringToBSTR(
const char* pSrc
)
);
}

进程内组件的装载与卸载:

客户程序调用COM库的CoCreateInstance或者CoGetClassObject函数创建COM对象,在
CoGetClassObject函数中,COM库根据系统注册表中的信息,找到类标识符CLSID对应的组件程序(DLL文件)的全路径,然后调用
LoadLibrary函数(CoLoadLibrary),并调用组件程序中的DllGetClassObject引出函
数,DllGetClassObject函数创建相应的类厂对象,并返回类厂对象的IClassFactory接口。客户程序继续调用类厂对象的
CreateInstance成员函数,由它负责COM对象的创建工作。

客户程序调用CoFreeUnusedLibraryes函数卸载组件,检测当前进程中的所有组件程序,当发现某个组件的DllCanUnloadNow函数返回TRUE时,就调用FreeLibrary(CoFreeLibrary)函数把组件从内存中卸出。

COM对象的接口原则

为了规范COM的接口机制,微软向COM开发者发布了COM对象的接口原则。
(1)IUnknown接口的等价性
同一个对象的Queryinterface的IID_IUnknown查询出来的IUnknown指针值应当相等。也就是说,每个对象的IUnknown指是唯一的。我们可以通过判断IUnknown指针是否相等来判断它们是否指向同一个对象。
(2)接口自反性,对一个接口来说,查询它本身应该是允许的。
设pPsychics是已赋值IPsychics的接口。那么pPsychics->QueryInterface(IID_IPsychics,(void **) &XXX);应当成功。
(3)接口对称性,当我们从一个接口查询到另一个接口时,那么我们再从结果接口还可以查询到原来的接口。

果pSrcPsychics->QueryInterface(IID_IDynamics,(void **)
&pDynamics);成功的话。那么pDynamics->QueryInterface(IID_IPsychics,(void
**) &pTarget);也相当成功。
(4)接口传递性。如果我们从第一个接口查询到了第二个接口,又从第二个接口查询到了第三接口。则我们应该能够从第三个接口查询到第一个接口。其它依此类推。
(5)接口查询时间无关性。当我们在某时查询到一个接口,那么在任意时刻也应该查询到这个接口。

HRESULT:

类别码(30~31位):00 调用成功,01 包含一些信息,10 警告,11错误。
自定义标志位(第29位):1 自定义类型。
操作码(16~28位):标识结果操作来源。
操作结果码(0~15位):反应操作状态。
S_OK,函数执行成功,S_FALSE,执行成功,返回FALSE,E_FAIL,执行失败,原因未知,E_NOMEMORY,内在分配失败,E_NOTIMPL,没有实现成员函数,E_NOTINTERFACE,未实现指定接口,用于QueryInterface.
使用FormatMessage函数可以获得该结果的说明字符。
使用SUCESSED或FAILED宏来对HRESULT类型的结果值作出成功或失败判断。

COM库的重用

1.包容

1. Class CB //保存包容组件接口
{ private:ISomeInterface *m_pSomeInterface; }
2. HRESULT result = ::CoCreateInstance(CLSID_CompA, NULL,  //在Init()中初始化组件A
                        CLSCTX_INPROC_SERVER,
                        IID_ISomeInterface, (void **)& m_pSomeInterface) ;
3.HRESULT __stdcall CB::SomeFunction() { return m_pSomeInterface->SomeFunction();
4.HRESULT CBFactory::CreateInterface(IUnknow *pUnknowOuter, const IID& iid, void **pv)
{ CB *pObj = new CB(); HRESULT hr = pObj->Init(); hr = pObj->QueryInterface(iid, pv);}

2.聚合

1. Class CB //保存包容组件IUnknown接口
{ private:IUnknown *m_pUnknownInner; }
2. HRESULT CB::QueryInterface(const IID& iid, void **ppv)
{ if ( iid == IID_SomeInterface ) {       return m_pUnknownInner->QueryInterface(iid, ppv) ;    } //转给内部对象A的QueryInterface
3.HRESULT CA::NondelegationQueryInterface(const IID& iid, void **ppv){//非委托IUnknown查询接口,COM不是通过类名来识别接口,而是通过vtable来调用接口成员函数。
  
 if ( iid == IID_IUnknown )    {        *ppv = (INondelegatingUnknown
*) this ;        ((IUnknown *)(*ppv))->AddRef() ;    }
    else
if ( iid == IID_SomeInterface )     {        *ppv = (ISomeInterface *)
this ;        ((ISomeInterface *)(*ppv))->AddRef() ;    }
    else    {        *ppv = NULL;        return E_NOINTERFACE ;    }    return S_OK;}
4.HRESULT CA::QueryInterface(const IID& iid, void **ppv){ //委托IUnknown查询接口
    if  ( m_pUnknownOuter != NULL )        return m_pUnknownOuter->QueryInterface(iid, ppv); //如果被聚合,返回外部对象的接口。
    else        return NondelegationQueryInterface(iid, ppv);}
5.HRESULT CB::Init(){ //创建对象A
IUnknown *pUnknownOuter = (IUnknown *)this;
HRESULT result = ::CoCreateInstance(CLSID_CompA, pUnknownOuter,   //传递IUnknown说明被聚合
                        CLSCTX_INPROC_SERVER,
                        IID_IUnknown, (void **)& m_pUnknownInner) ;//得到组件A的非委托IUnknown
result
= m_pUnknownInner->QueryInterface(IID_SomeInterface, (void
**)&m_pSomeInterface);
//检测是否有接口SomeInterface,调用的其实是NondelegationQueryInterface()函数
if (FAILED(result))    {        m_pUnknownInner->Release();        return E_FAIL;    }
6. CA::CA (IUnknown *pUnknownOuter){    m_pUnknownOuter = pUnknownOuter; } //构造时保存B的IUnknown接口
7. HRESULT CAFactory::CreateInstance(IUnknown *pUnknownOuter, const IID& iid, void **ppv){
  
 if ( ( pUnknownOuter != NULL ) && ( iid != IID_IUnknown ) )  
 {        return CLASS_E_NOAGGREGATION;    }
//如果被聚合,IID必须是IUnknown.防止暴露其它接口。
    CA *pObj=new CA (pUnknownOuter);
   
HRESULT    hr = pObj->NondelegationQueryInterface(iid, ppv);   if
(hr != S_OK) {   delete pObj;   }      return hr;   }
//必须返回非委托IUnknown接口

8. HRESULT CBFactory::CreateInstance(IUnknown *pUnknownOuter, const IID& iid, void **ppv){
    CB  *pObj = new CB ();   if (NULL==pObj)        return hr;   
     pObj->AddRef();  // The Reference count of pObj is 1
    HRESULT hr = pObj->Init();
    hr=pObj->QueryInterface(iid, ppv);
    pObj->Release();    // The Reference count of pObj is 1
   return hr;}

 

抱歉!评论已关闭.