MyCom

来源:互联网 发布:淘宝福袋图片 编辑:程序博客网 时间:2024/05/25 18:10

一、COM原理与实现

多重继承方式

class CDictionary : public IDictionary , public ISpellCheck
{
public :
     CDictionary();
     ~CDictionary();
public :
    // IUnknown member function
     virtual HRESULT QueryInterface(const IID& iid, void **ppv) ;
     virtual ULONG AddRef() ; 
     virtual ULONG Release() ;
     ......
private :
     int m_Ref ;
     ......
};
     

依次查询iid是否对应(如果接口较多?)

HRESULT CDictionary::QueryInterface(const IID& iid,
void **ppv)
{
     if ( iid == IID_IUnknown ) {
     *ppv = static_castthis ;
     ((IDictionary *)(*ppv))->AddRef() ;
     } 
     else if ( iid == IID_Dictionary ) {
     *ppv = static_castthis ;
     ((IDictionary *)(*ppv))->AddRef() ;
     } 
     else if ( iid == IID_SpellCheck ) {
     *ppv = static_castthis ;
     ((ISpellCheck *)(*ppv))->AddRef() ;
     } 
     else {
     *ppv = NULL;
     return E_NOINTERFACE ;
     }
     return S_OK;}
return S_OK;
}

CreatObject

BOOL _stdcall CreateObject(const  CLSID&  clsid,  const  IID&  iid,  void  **ppv) 

    if  (clsid  ==  CLSID_Dictionary  )  { 
       CDictionary  *pObject  =  new  CDictionary;  
        HRESULT result = pobject->QueryInterface(id, ppv);
        return (result == S_OK) ? TEUR : FALSE;

类厂(COM规定每一对象类均应有相应的类厂)

struct IClassFactory : public IUnknown
{
    virtual HRESULT _stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid,
     void** ppvObject ) = 0;
    virtual HRESULT _stdcall LockServer( BOOL bLock ) = 0;};
类厂使用: HRESULT DllGetClassObject(const CLSID& clsid, const IID& iid,     void** ppv );
参考:http://blog.csdn.net/guogangj/archive/2006/10/30/1357576.aspx

CoGetClassObject  / CoCreatInstance / CoCreatInstanceEX

 CoCreatInstance

二、COM特性

包容与聚合

定义接口:
class ISomeInterface : public IUnknown
{
public:
virtual HRESULT __stdcall SomeFunction() = 0;
};
class IOtherInterface : public IUnknown
{
public:
virtual HRESULT __stdcall OtherFunction() = 0;
};
包容:外部对象定义
class CB : public ISomeInterface , public IOtherInterface
{
private :
    ISomeInterface *m_pSomeInterface;
};
包容:外部对象的实现
HRESULT CB::Init()
{
HRESULT result = ::CoCreateInstance(CLSID_ComponentA, NULL, 
              CLSCTX_INPROC_SERVER, IID_ISomeInterface, (void **)&m_pSomeInterface) ;
}
包容:外部对象类厂的实现
HRESULT CBFactory::CreateInstance(IUnknown *pUnknownOuter, const IID& iid, void **ppv)
{
    CB *pObj; HRESULT hr; *ppv=NULL;
    if (pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
    pObj=new CB (); if (pObj == NULL) return E_OUTOFMEMORY; hr = pObj->Init();
    if (FAILED(hr) ) {g_ObjectNumber --; delete pObj;}
    //Obtain the first interface pointer (which does an AddRef)
    hr=pObj->QueryInterface(iid, ppv);  return hr;
}

聚合:外部对象的定义
class CB : public IOtherInterface
{
HRESULT Init();
private :
IUnknown *m_pUnknownInner; // pointer to A's IUnknown
};
聚合:外部对象的QueryInterface
HRESULT CB::QueryInterface(const IID& iid, void **ppv)
{
if ( iid == IID_IUnknown ) {*ppv = (IUnknown *) this ;((IUnknown *)(*ppv))->AddRef() ;
} else if ( iid == IID_OtherInterface ) {*ppv = (IOtherInterface *) this ;((IOtherInterface *)(*ppv))->AddRef() ;
} else if ( iid == IID_SomeInterface ) {return m_pUnknownInner->QueryInterface(iid, ppv) ;
} else {*ppv = NULL;return E_NOINTERFACE ;}
return S_OK;
}

聚合:定义两种 IUnknown接口              

解决IUnknown接口指针不一致的问题(因为C++类不能同时继承实现两个IUnknown,所以为非委托接口定义一个新的类)。而且被聚合接口ISomeInterface请求不到聚合接口IOtherInterface,这与COM规范矛盾:对象创建函数CoCreateInstance的第二个参数pUnknownOuter用于解决聚合中IUnknown接口的问题。当其为NULL时表示正常使用,不为NULL时被聚合使用。内部对象实现两个IUnknown 分别用于这两种情况:委托IUnknown和非委托IUnknowndelegating unknownnondelgating unknown)。

class INondelegationUnknown
{
public:
virtual HRESULT __stdcall NondelegationQueryInterface(const IID& iid, void **ppv) = 0 ;
virtual ULONG __stdcall NondelegationAddRef() = 0;
virtual ULONG __stdcall NondelegationRelease() = 0;
};
内部对象的定义
class CA : public ISomeInterface, public INondelegationUnknown
{
protected:
ULONG m_Ref;
public:
CA ( IUnknown *pUnknownOuter);
~ CA ( );
public :
virtual HRESULT __stdcall QueryInterface(const IID& iid, void **ppv);
virtual ULONG __stdcall AddRef() ;
virtual ULONG __stdcall Release() ;
virtual HRESULT __stdcall NondelegationQueryInterface(const IID& iid, void **ppv) ;
virtual ULONG __stdcall NondelegationAddRef() ;
virtual ULONG __stdcall NondelegationRelease() ;
…….
private :
IUnknown *m_pUnknownOuter; // pointer to outer IUnknown
};
聚合:非委托IUnknown接口的实现
AddRef和Release与正常情况相同
HRESULT CA:: NondelegationQueryInterface(const IID& iid, void **ppv)
{
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;}
聚合:委托IUnknown接口的实现
ULONG CA:: AddRef ()
{ if ( m_pUnknownOuter != NULL ) return m_pUnknownOuter->AddRef();
else return NondelegatingAddRef(); }
HRESULT CA:: QueryInterface(const IID& iid, void **ppv)
{ if ( m_pUnknownOuter != NULL ) return m_pUnknownOuter->QueryInterface(iid, ppv);
else return NondelegatingQueryInterface(iid, ppv); }
聚合:外部对象创建
外部对象类厂在构造了CB之后,调用Init函数,类厂的CreateInstance函数与包容模型相同.但CB::Init函数不同:
HRESULT CB::Init()
{ IUnknown *pUnknownOuter = (IUnknown *)this;
HRESULT result = ::CoCreateInstance(CLSID_ComponentA, pUnknownOuter, CLSCTX_INPROC_SERVER,
IID_IUnknown, (void **)& m_pUnknownInner) ;
if (FAILED(result)) return E_FAIL;
else return S_OK; }
聚合:外部对象的析构
CB::~CB ( ) { if (m_pUnknownInner ! = NULL)  m_pUnknownInner->Release() ; }
内部对象创建
HRESULT CAFactory::CreateInstance(IUnknown *pUnknownOuter,
const IID& iid, void **ppv)
{
// iid must be IID_IUnknown for aggregating
if ( ( pUnknownOuter != NULL ) && ( iid != IID_IUnknown ) ) { return CLASS_E_NOAGGREGATION; }
*ppv=NULL;   //Create the object passing function to notify on destruction.
CA *pObj=new CA (pUnknownOuter);  if (pObj == NULL) return E_OUTOFMEMORY;  
//Obtain the first interface pointer (which does an AddRef)
HRESULT hr = pObj->NondelegatingQueryInterface(iid, ppv); return hr;
}
聚合:内部对象的构造函数
CA::CA (IUnknown *pUnknownOuter)
{ m_pUnknownOuter = pUnknownOuter; }
聚合:外部对象的创建(修订)
HRESULT CB::Init()
{
IUnknown *pUnknownOuter = (IUnknown *)this;
HRESULT result = ::CoCreateInstance(CLSID_CompA, pUnknownOuter,
CLSCTX_INPROC_SERVER,
IID_IUnknown, (void **)& m_pUnknownInner) ;
if (FAILED(result)) return E_FAIL;

result = m_pUnknownInner->QueryInterface(IID_ISomeInterface,
(void **)&m_pSomeInterface);
if (FAILED(result)) {
m_pUnknownInner->Release();
return E_FAIL;
}
pUnknownOuter->Release();
return S_OK;
}
聚合:外部对象的创建(修订)
HRESULT CBFactory::CreateInstance(IUnknown *pUnknownOuter,
const IID& iid, void **ppv)
{
CB *pObj; HRESULT hr; *ppv=NULL;
if (NULL != pUnknownOuter) return CLASS_E_NOAGGREGATION;

pObj=new CB ();
if (pObj == NULL) return E_OUTOFMEMORY;

pObj->AddRef(); // The Reference count of pObj is 1
hr = pObj->Init();
if (FAILED(hr) ) { g_CompBNumber --; delete pObj;
return E_FAIL; }
hr=pObj->QueryInterface(iid, ppv);
pObj->Release(); // The Reference count of pObj is 1
return hr;
}
聚合:外部对象的析构(修订)
CB::~CB ( )
{
m_Ref = 1;
IUnknown *pUnknownOuter = this;
pUnknownOuter->AddRef ( );
if (m_pSomeInterface != NULL)
m_pSomeInterface->Release();
if (m_pUnknownInner != NULL)
m_pUnknownInner->Release() ;
}

用嵌套类实现COM接口

class CDictionary
{
…… //构造函数和析构函数
用嵌套类实现COM接口
class CDictionary
{
    //构造函数和析构函数
    HRESULT __stdcall QueryInterface(REFIID iid, void** ppvObj);
    ULONG __stdcall AddRef();
    ULONG __stdcall Release();
    class XDictionaryObj : public IDictionary {
    public:
        CDictionary * m_pParent;
        virtual HRESULT __stdcall QueryInterface(REFIID iid, void** ppvObj);
        virtual ULONG __stdcall AddRef();
        virtual ULONG __stdcall Release();
        virtual BOOL __stdcall Initialize();
            ...
        virtual void __stdcall FreeLibrary();
    } m_dictionaryObj;

    class XSpellCheckObj : public ISpellCheck {
    public:
        CDictionary * m_pParent;
        virtual HRESULT __stdcall QueryInterface(REFIID iid, void** ppvObj);
        virtual ULONG __stdcall AddRef();
        virtual ULONG __stdcall Release();
        virtual BOOL __stdcall CheckWord (String word, String *);
    } m_spellCheckObj;
    private :
    struct DictWord *m_pData;
    char *m_DictFilename[128];
    int m_Ref ;
    int m_nWordNumber, m_nStructNumber;};

CDictionary::CDictionary()
{
     // Initializtion
    m_dictionaryObj. m_pParent = this;
    m_spellCheckObj. m_pParent = this;
}
HRESULT CDictionary::QueryInterface(const IID& iid, void **ppvObj)
{
    if (iid == IID_IUnknown || iid == IID_Dictionary) {*ppvObj = &m_dictionaryObj;AddRef();return S_OK;
    } else if (iid == IID_SpellCheck) {*ppvObj = &m_spellCheckObj;AddRef();return S_OK;}
    *ppv = NULL; return E_NOINTERFACE ;
}
ULONG CDictionary::XDictionaryObj::QueryInterface(const IID& iid, void **ppvObj)
{  return m_pParent->QueryInterface(iid, ppvObj); }
......

MFC与COM

接口映射表的宏定义
#define BEGIN_INTERFACE_MAP(theClass, theBase) /
const AFX_INTERFACEMAP* PASCAL theClass::_GetBaseInterfaceMap() /
{ return &theBase::interfaceMap; } /
const AFX_INTERFACEMAP* theClass::GetInterfaceMap() const /
{ return &theClass::interfaceMap; } /
AFX_COMDAT const AFX_DATADEF /
AFX_INTERFACEMAP theClass::interfaceMap = /
{ &theClass::_GetBaseInterfaceMap, &theClass::_interfaceEntries[0], }; /
AFX_COMDAT const AFX_DATADEF
AFX_INTERFACEMAP_ENTRY theClass::_interfaceEntries[] = /
{ /
#define INTERFACE_PART(theClass, iid, localClass) /
{ &iid, offsetof(theClass, m_x##localClass) }, /
#define END_INTERFACE_MAP() /
{ NULL, (size_t)-1 } /}; /

CCmdTarget类实现IUnknown
public:
 // data used when CCmdTarget is made OLE aware
 long m_dwRef;
 LPUNKNOWN m_pOuterUnknown; // external controlling unknown if != NULL
 DWORD m_xInnerUnknown; // place-holder for inner controlling unknown
public:
 // advanced operations
 void EnableAggregation(); // call to enable aggregation
 void ExternalDisconnect(); // forcibly disconnect
 LPUNKNOWN GetControllingUnknown();
 // get controlling IUnknown for aggregate creation
public:
 // these versions do not delegate to m_pOuterUnknown
 DWORD InternalQueryInterface(const void*, LPVOID* ppvObj);
 DWORD InternalAddRef();
 DWORD InternalRelease();
 // these versions delegate to m_pOuterUnknown
 DWORD ExternalQueryInterface(const void*, LPVOID* ppvObj);
 DWORD ExternalAddRef();
 DWORD ExternalRelease();

DWORD CCmdTarget::InternalQueryInterface(const void* iid, LPVOID* ppvObj)
{ // check local interfaces
 if ((*ppvObj = GetInterface(iid)) != NULL) { ExternalAddRef();  return S_OK; }  // interface was found -- add a reference
 // check aggregates
 if ((*ppvObj = QueryAggregates(iid)) != NULL) return S_OK;
 return (DWORD)E_NOINTERFACE;  // interface ID not found, fail the call
}
CCmdTarget中ExternalXXX成员实现
DWORD CCmdTarget::ExternalAddRef()
{ // delegate to controlling unknown if aggregated
 if (m_pOuterUnknown != NULL)  return m_pOuterUnknown->AddRef();
 return InternalAddRef();
}
DWORD CCmdTarget::ExternalRelease() // …...
// QueryInterface that is exported to normal clients
DWORD CCmdTarget::ExternalQueryInterface(const void* iid, LPVOID* ppvObj)
{
 // delegate to controlling unknown if aggregated
 if (m_pOuterUnknown != NULL)  return m_pOuterUnknown->QueryInterface(*(IID*)iid, ppvObj);
 return InternalQueryInterface(iid, ppvObj);
}
嵌套类内部实现IUnknown的成员函数
STDMETHODIMP_(ULONG) CDictionary::XDictionary::QueryInterface (
const void* iid, LPVOID* ppvObj)
{
 METHOD_PROLOGUE_EX_(CDictionary, Dictionary)
 return pThis->ExternalQueryInterface (iid, ppvObj);
}

COM引出函数和类厂实现
在AppWizard中选中"Automation"检查框
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return AfxDllGetClassObject(rclsid, riid, ppv);
}
STDAPI DllCanUnloadNow(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return AfxDllCanUnloadNow();
}
// by exporting DllRegisterServer, you can use regsvr.exe
STDAPI DllRegisterServer(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
COleObjectFactory::UpdateRegistryAll();
return S_OK;
}
前两个函数是COM程序所必须的。

MFC提供了通用的类厂COleObjectFactory,由CCmadTarget派生。

MFC版本的字典对象类定义

CCmdTarget实现了内部和外部IUnknown分别对应聚合模型中的非委托与委托IUnknown。
class CDictionary : public CCmdTarget
{
    DECLARE_DYNCREATE(CDictionary)
    CDictionary(); // protected constructor used by dynamic creation
    DECLARE_INTERFACE_MAP()
    ......
    // IDictionary
    BEGIN_INTERFACE_PART(Dictionary, IDictionary)
    INIT_INTERFACE_PART(CDictionary, Dictionary)
    STDMETHOD_(BOOL, Initialize)();
    ……
    STDMETHOD_(void, FreeLibrary)();
    END_INTERFACE_PART_STATIC(Dictionary)
    // ISpellCheck
    BEGIN_INTERFACE_PART(SpellCheck, ISpellCheck)
    INIT_INTERFACE_PART(CDictionary, SpellCheck)
    STDMETHOD_(BOOL, CheckWord)(LPOLESTR, LPOLESTR *);
    END_INTERFACE_PART_STATIC(SpellCheck)
};
MFC版本的字典对象类实现
STDMETHODIMP_(ULONG) CDictionary::XDictionary::AddRef()
{
 METHOD_PROLOGUE_EX_(CDictionary, Dictionary)
 return pThis->ExternalAddRef();
}

三、自动化对象


New Class: CMyAutoObj
base Class : CCmdTarget
Automation: Createable by type ID: (AutoComp.MyAutoObj)
加入属性x,y,方法MoveTo

.h文件中
  //{{AFX_DISPATCH(CPointObj)
  afx_msg long GetX();
  afx_msg void SetX(long nNewValue);
  afx_msg void MoveTo(long nx, ong ny); 
  //}}AFX_DISPATCH
.cpp文件中
  BEGIN_DISPATCH_MAP(CCalcDlg, CDialog)
 //{{AFX_DISPATCH_MAP(CCalcDlg)
 DISP_PROPERTY_EX(CPointObj, "X", GetX, SetX, VT_I4)
 DISP_PROPERTY_EX(CPointObj, "Y", GetY, SetY, VT_I4)
 DISP_FUNCTION(CPointObj, "MoveTo", MoveTo, VT_EMPTY, VTS_I4 VTS_I4)
 //}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()

 COleDispatchDriver类
class IPointObj : public COleDispatchDriver
{
public:
  IPointObj(){}
 IPointObj(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
 IPointObj(const IPointObj& dispatchSrc) :  COleDispatchDriver(dispatchSrc) {}
public:
 long GetX();
 void SetX(long);
 long GetY();
 void SetY(long);
public:
 void MoveTo(long nx, ong ny);
}
long IPointObj::GetX(long propVal)
{
 long result;
 GetProperty(0x1, VT_14, (void*)&result);
 return result;
}
void IPointObj::SetX()
{
 SetProperty(0x1, VT_14, propVal);
}
void IPointObj::MoveTo(long nx, ong ny)
{
 static BYTE parms[] =  VTS_I4, VTS_I4;
 InvokeHelper(0x3, DISPATCH_METHOD, VT_EMPTY, NULL, parms, nx, ny);
}

 

原创粉丝点击