ATL仿真

类别:VC语言 点击:0 评论:0 推荐:

这几天学习ATL,想起了《深入浅出MFC》中的方法:仿真,折腾了大半天,弄出了点东西,愿与正在ATL的坚韧难懂中挣扎却不懈努力的同志共享。编写的时候我怕写成了ATL的COPY所以没有看它的源码,很多名字只凭记忆,还有些名字我觉得我所取的名字自己更易理解,所以名字可能有点不同,别怪我!由于怕又陷入了那个大迷宫里,所以没有客气的把一些初学者不好理解的东西都“砍掉”,比如,我在仿真时完全没有考虑聚合的情况。另外,我没有引用其它类库的东西(以免你要到处找类库手册),甚至没有没有用API。里头加了些注解。不说了,你看吧!但愿对你有点用。

//---------AtlMy.h

#include <iostream.h>

//常用类型定义
typedef unsigned long HRESULT;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef int BOOL;

//返回值
#define S_OK 0
#define E_FAIL 1;

#define INTERFACE class

#ifdef _DEBUG_ON
#define ASSERT(b) {if(!b) __asm int 3h}
#else
 #define ASSERT(b)
#endif

//计算接口的偏移
#define _ATL_PACKING 8
#define offsetofclass(base, derived) ((DWORD)(static_cast<base*>((derived*)_ATL_PACKING))-_ATL_PACKING)

//标识符类型定义
typedef unsigned long GUID;
typedef GUID IID;
typedef GUID CLSID;
#define DEFINEIID(X,N) const IID_##X = N

//调试输出
#ifdef _DEBUG_ON
#define TRACELN(x) cout << " | DEBUG : " << x <<endl
#define TRACE(x) cout << " | DEBUG : " << x
#define TRACEA(x) cout << x
#define TRACELNA(x) cout << x <<endl
#else
#define TRACELN(x)
#define TRACE(x)
#define TRACEA(x)
#define TRACELNA(x)
#endif
//定义接口方法
#define METHOD(X) \
public: \
 virtual HRESULT X

//定义IUnknown
DEFINEIID(IUnknown,0x010001);
INTERFACE IUnknown
{
 METHOD(QueryInterface)(IID iid,void** ppv) = 0;
 METHOD(AddRef)(void) = 0;
 METHOD(Release)(void) = 0;
};

//定义IClassFactory
DEFINEIID(IClassFactory,0x347a24);
INTERFACE IClassFactory : public IUnknown
{
 METHOD(CreateInstance)( IUnknown * pUnkOuter,
  IID riid, void ** ppvObject) = 0;
 METHOD(LockServer)(BOOL bLook) = 0;
};

//define class mapping entry struct
typedef HRESULT(* CreateFunc)(void* pv, IID riid, void** ppv);

typedef struct{
 CLSID clsid;
 CreateFunc pfnCreateObject;
 CreateFunc pfnCreateInstance;
 IUnknown* pCF; //类厂IUnknown
}_OBJECT_MAP_ENTRY;


#define DEFINECLSID(X,N) const CLSID_##X = N

#define BEGIN_OBJECT_MAP(x) \
 static _OBJECT_MAP_ENTRY x[] = {

#define OBJECT_ENTRY(clsid,class) \
 {clsid,class::_ClassFactory::CreateInstance, \
   class::_CreatorObject::CreateInstance , NULL},

#define OBJECT_ENTRYEX(class) \
 {CLSID_##class,class::_ClassFactory::CreateInstance, \
   class::_CreatorObject::CreateInstance , NULL},

#define END_OBJECT_MAP() \
  {0,NULL,NULL,NULL} \
 };

 

//define Interface map entry struct
typedef struct{
 IID iid;
 DWORD dw;
}_INTERFACES_ENTRY;
//define interface mapping macro
#define BEGIN_INTERFACES_MAP(CN) \
public: \
 typedef CN _ComClass; \
 const static _INTERFACES_ENTRY* _GetInterfaceMap() \
 { \
  static _INTERFACES_ENTRY _Entry[] = \
  { \
   {IID_IUnknown,0},


#define INTERFACE_ENTRY(IN) \
   {IID_##IN,offsetofclass(IN,_ComClass)},

#define END_INTERFACES_MAP() \
   {0,0} \
  };\
  return &_Entry[1]; \
 } \
 METHOD(QueryInterface)(IID iid,void** ppv) = 0; \
 METHOD(AddRef)(void) = 0; \
 METHOD(Release)(void) =0;


//类定义
template<typename T>
class CComObjectRoot
{
public:
 METHOD(FinalAddRef)(void)
 {
  m_dwRef ++;
  TRACE(" AddRef  m_dwRef = ");
  TRACELNA(m_dwRef);
  return S_OK;
 }
 METHOD(FinalRelease)(void)
 {
  m_dwRef --;
  ASSERT((m_dwRef >= 0));
  TRACE(" Release  m_dwRef = ");
  TRACELNA(m_dwRef);
 
  if(m_dwRef <= 0){
   delete this;
   TRACELN(" Delete ... ");
  }
  return S_OK;
 }
 METHOD(FinalQueryInterface)(void* pThis,IID iid,void** ppv)
 {
  ASSERT(pThis && iid);
  const _INTERFACES_ENTRY* pEntry = T::_GetInterfaceMap();
  ASSERT(pEntry);
  
  while(!(pEntry->dw == 0 && pEntry->iid ==0))
  {
   if(iid == IID_IUnknown)
   {
    *ppv = (IUnknown*)((T*)pThis);
    FinalAddRef();
    TRACELN(" QueryInterface IUnknown ");
    return S_OK;
   }
   
   if(iid == pEntry->iid){
    *ppv = (void *)(((DWORD)pThis) + pEntry->dw);
    FinalAddRef();
    TRACELN(" QueryInterface OK");
    return S_OK;
   }
   pEntry ++;
  }
  TRACELN(" QueryInterface Failed ");
  return E_FAIL;
 }
public: 
 CComObjectRoot()
 {
  m_dwRef = 0;
 }
 void SetVoid(void* pv){}
 DWORD m_dwRef;
};
template<typename T>
class CComObject  : public T
{
 METHOD(QueryInterface)(IID iid,void** ppv)
 {
  return FinalQueryInterface(this,iid,ppv);
 }
 METHOD(AddRef)(void)
 {
  return FinalAddRef();
 }
 METHOD(Release)(void){
  return FinalRelease();
 }
};

class CComClassFactory :
 public CComObjectRoot<CComClassFactory>,
 public IClassFactory
{
 METHOD(CreateInstance)(IUnknown* pUnkOuter , IID iid,
  void** ppv)
 {
  return m_pfnCreateInstance(pUnkOuter ,
    iid , ppv);
 }

 METHOD(LockServer)(BOOL bLock)
 {
  return S_OK;
 }
 void SetVoid(void* pv)
 {
  m_pfnCreateInstance = (CreateFunc )pv;
 }
 CreateFunc m_pfnCreateInstance;

 BEGIN_INTERFACES_MAP(CComClassFactory)
  INTERFACE_ENTRY(IClassFactory)
 END_INTERFACES_MAP()
};

template<typename T>
class CComCreator
{
public:
 static HRESULT CreateInstance(void* pv, IID riid, void** ppv)
 {
  ASSERT(riid);
  T* p = new T;
  if(p->QueryInterface(riid,ppv) != S_OK){
   delete p;
   return E_FAIL;
  }
  p->SetVoid(pv);
  return S_OK;
 }

};

#define DEFINE_CLASSFACTORY() \
 typedef CComCreator< CComObject< CComClassFactory> > _ClassFactory;

#define DEFINE_OBJECT(x) \
 typedef CComCreator< CComObject< x > > _CreatorObject;

template<typename T>
class CComCoClass
{
public:
 DEFINE_CLASSFACTORY()
 DEFINE_OBJECT(T)
};

class CComModule
{
public:
 void Init(_OBJECT_MAP_ENTRY* p)
 {
  m_pObjectMap = p;
 }
 void Trim()
 {
  ASSERT(m_pObjectMap);
  _OBJECT_MAP_ENTRY* pEntry = m_pObjectMap;
  while(pEntry->clsid != NULL)
  {
   if(pEntry->pCF != NULL)
    pEntry->pCF->Release();
   pEntry ++; 
  }

 }
 _OBJECT_MAP_ENTRY* m_pObjectMap;
 METHOD(GetClassObjcet)(CLSID clsid, IID riid, void** ppv)
 {
  ASSERT(m_pObjectMap);
  _OBJECT_MAP_ENTRY* pEntry = m_pObjectMap;
  while(pEntry->clsid != NULL)
  {
   if(pEntry->clsid == clsid)
   {
    if(pEntry->pCF == NULL){
     HRESULT hRes = pEntry->pfnCreateObject(pEntry->pfnCreateInstance,
      riid,(void**)&pEntry->pCF);
     *ppv = (void *)pEntry->pCF;
     return S_OK;
    }
    else
    {
     *ppv = (void *)pEntry->pCF;
     return S_OK;
    }
   
   }
   pEntry ++; 
  }
  return E_FAIL;
 }
};

 

 

//Test.cpp

#include "stdafx.h"
#include "atlmy.h"

DEFINEIID(IMy,0x34242);
INTERFACE IMy : public IUnknown
{
 METHOD(F1)(void) = 0;
};

DEFINECLSID(MyClass,0x25346);
class MyClass :
 public CComObjectRoot<MyClass>,
 public CComCoClass<MyClass>,
 public IMy
{
 METHOD(F1)(void)
 {
  cout << "Hello" <<endl;
  return S_OK;
 }
 BEGIN_INTERFACES_MAP(MyClass)
  INTERFACE_ENTRY(IMy)
 END_INTERFACES_MAP()
};

BEGIN_OBJECT_MAP(ObjectMap)
 OBJECT_ENTRYEX(MyClass)
END_OBJECT_MAP()

CComModule _Module;

int main(int argc, char* argv[])
{
 _Module.Init(ObjectMap);
 IClassFactory *pCF = NULL;
 IMy* pMy = NULL;
 
 _Module.GetClassObjcet(CLSID_MyClass,IID_IClassFactory,(void**)&pCF);
 pCF->CreateInstance(NULL,IID_IMy,(void** )&pMy);

 IMy* pMy1 = NULL;
 IClassFactory *pCF1 = NULL;
 _Module.GetClassObjcet(CLSID_MyClass,IID_IClassFactory,(void**)&pCF1);
 pCF1->CreateInstance(NULL,IID_IMy,(void** )&pMy1);
 pMy1->F1();
 pMy1->Release();
 pMy->F1();
 pMy->Release();

 _Module.Trim();

 return 0;
}


 

本文地址:http://com.8s8s.com/it/it2803.htm