这几天学习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; }

|