通过ATL实现类厂和组件的创建
来源:互联网 发布:视频剪辑的电脑软件 编辑:程序博客网 时间:2024/04/28 01:36
类工厂的实现,组件的创建过程
1. 在*_Server.cpp 中有
- BEGIN_OBJECT_MAP(ObjectMap)
- OBJECT_ENTRY(CLSID_Math, CMath)
- END_OBJECT_MAP()
展开后是这样:
- struct _ATL_OBJMAP_ENTRY30
- {
- const CLSID* pclsid;
- HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);
- _ATL_CREATORFUNC* pfnGetClassObject;
- _ATL_CREATORFUNC* pfnCreateInstance;
- IUnknown* pCF;
- DWORD dwRegister;
- _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription;
- _ATL_CATMAPFUNC* pfnGetCategoryMap;
- void (WINAPI *pfnObjectMain)(bool bStarting);
- };
- static ATL::_ATL_OBJMAP_ENTRY ObjectMap[] =
- {
- {
- &CLSID_Math,
- CMath::UpdateRegistry,
- CMath::_ClassFactoryCreatorClass::CreateInstance,
- CMath::_CreatorClass::CreateInstance,
- NULL,
- 0,
- CMath::GetObjectDescription,
- CMath::GetCategoryMap,
- CMath::ObjectMain
- },
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
- };
定义了一个_ATL_OBJMAP_ENTRY 类型的全局数组变量 ObjectMap
然后在 Dll 被载入时用这个数组初始化全局的 _Module 变量
- CComModule _Module;
- BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
- {//......
- if (dwReason == DLL_PROCESS_ATTACH)
- {
- _Module.Init(ObjectMap, hInstance);
- }
- }
- inline HRESULT CComModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE /*h*/, const GUID* plibid) throw()
- {//......
- m_pObjMap = p;
- _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap;
- while (pEntry->pclsid != NULL)
- {
- pEntry->pfnObjectMain(true); //这里就是 CMath::ObjectMain
- pEntry++;
- }
- }
当用户代码中调用 CoCreateInstance 时
HRESULT hr = CoCreateInstance( CLSID_Math,
NULL,
CLSCTX_INPROC,
IID_IMath,
(void**) &pMath );
Dll 中的 DllGetClassObject 会被调用,最终调用 CMath::_ClassFactoryCreatorClass::CreateInstance 创建CMath组件
- STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
- {
- return _Module.GetClassObject(rclsid, riid, ppv);
- }
- inline HRESULT CComModule::GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw()
- {
- _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap;
- while (pEntry->pclsid != NULL)
- {
- if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid))
- {
- //pEntry->pfnGetClassObject == CMath::_ClassFactoryCreatorClass::CreateInstance
- //pEntry->pfnCreateInstance == CMath::_CreatorClass::CreateInstance
- pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF);
- pEntry->pCF->QueryInterface(riid, ppv);
- break;
- }
- pEntry++;
- }
- }
接下来看 CComCoClass 又是如何帮助实现 CMath::_ClassFactoryCreatorClass::CreateInstance 创建类厂的
- class ATL_NO_VTABLE CMath :
- public CComObjectRootEx<CComSingleThreadModel>,
- public CComCoClass<CMath, &CLSID_Math>,
- //......
- {
- }
- template <class T, const CLSID* pclsid = &CLSID_NULL> //T = CMath, pclsid = CLSID_Math
- class CComCoClass
- {
- public:
- //DECLARE_CLASSFACTORY()
- //DECLARE_AGGREGATABLE(T)
- typedef ATL::CComCreator< ATL::CComObjectCached< ATL::CComClassFactory > > _ClassFactoryCreatorClass;
- typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;
- typedef T _CoClass;
- template <class Q>
- static HRESULT CreateInstance(IUnknown* punkOuter, Q** pp)
- {
- return T::_CreatorClass::CreateInstance(punkOuter, __uuidof(Q), (void**) pp);
- }
- };
可见在 CComCoClass 中有两个typedef的定义,
_ClassFactoryCreatorClass 用于创建类厂
而 _CreatorClass用于创建组件实例
DllGetClassObject 最终调用了其中的 _ClassFactoryCreatorClass 的 CreateInstance函数创建类厂
将 _ClassFactoryCreatorClass 展开
- //typedef ATL::CComCreator< ATL::CComObjectCached< ATL::CComClassFactory > > _ClassFactoryCreatorClass;
- template <class T1> //T1 = ATL::CComObjectCached< ATL::CComClassFactory > 类厂
- //T1 = ATL::CComCreator< ATL::CComObject< CMath > >, ATL::CComCreator< ATL::CComAggObject< CMath > > 组件
- class CComCreator
- {
- public:
- static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
- {
- *ppv = NULL;
- HRESULT hRes = E_OUTOFMEMORY;
- T1* p = new T1(pv)); //这里创建了组件或类厂
- if (p != NULL)
- {
- p->SetVoid(pv); //pv = CMath::_CreatorClass::CreateInstance
- p->InternalFinalConstructAddRef();
- hRes = p->_AtlInitialConstruct();
- if (SUCCEEDED(hRes))
- hRes = p->FinalConstruct();
- if (SUCCEEDED(hRes))
- hRes = p->_AtlFinalConstruct();
- p->InternalFinalConstructRelease();
- if (hRes == S_OK)
- hRes = p->QueryInterface(riid, ppv); //获取组件接口指针
- if (hRes != S_OK)
- delete p;
- }
- return hRes;
- }
- };
DllGetClassObject 调用
- //pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF);
- CMath::_ClassFactoryCreatorClass::CreateInstance (CMath::_CreatorClass::CreateInstance, __uuidof(IUnknown), (LPVOID*)NULL);
然后在这里面创建了类厂 :ATL::CComObjectCached< ATL::CComClassFactory >* p = new ATL::CComObjectCached< ATL::CComClassFactory >(pv));
最终获得类厂的接口 :p->QueryInterface(riid, ppv);
类厂类是ATL::CComClassFactory 它的定义
- typedef HRESULT (WINAPI _ATL_CREATORFUNC)(void* pv, REFIID riid, LPVOID* ppv);
- class CComClassFactory :
- public IClassFactory,
- public CComObjectRootEx<CComGlobalsThreadModel>
- {
- public:
- BEGIN_COM_MAP(CComClassFactory)
- COM_INTERFACE_ENTRY(IClassFactory)
- END_COM_MAP()
- STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
- {
- HRESULT hRes = E_POINTER;
- *ppvObj = NULL;
- if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid)) //检查参数
- {
- ATLTRACE(atlTraceCOM, 0, _T("CComClassFactory: asked for non IUnknown interface while creating an aggregated object"));
- hRes = CLASS_E_NOAGGREGATION;
- }
- else
- hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
- return hRes;
- }
- void SetVoid(void* pv) //pv = CMath::_CreatorClass::CreateInstance
- {
- m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;
- }
- _ATL_CREATORFUNC* m_pfnCreateInstance;
- };
这里面有趣的是 SetVoid(void* pv) 它将 CMath::_CreatorClass::CreateInstance 传给了类厂指针成员变量 _ATL_CREATORFUNC* m_pfnCreateInstance
然后,在调用类厂 CreateInstance 创建对象实例时, 它会在检查参数后,调用 CMath::_CreatorClass::CreateInstance
那再看看 CMath::_CreatorClass::CreateInstance 会是如何实现创建组件实例
- typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;
- template <class T1, class T2> //T1 = ATL::CComCreator< ATL::CComObject< CMath > >, T2 = ATL::CComCreator< ATL::CComAggObject< CMath > >
- class CComCreator2
- {
- public:
- static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
- {
- ATLASSERT(ppv != NULL);
- return (pv == NULL) ?
- ATL::CComCreator< ATL::CComObject< CMath > >::CreateInstance(NULL, riid, ppv) :
- ATL::CComCreator< ATL::CComAggObject< CMath > >::CreateInstance(pv, riid, ppv);
- }
- };
它会通过pv参数判断组件是否组合,然后选择相应的创建模板类
-------------------------------------------------------------------------------------------------------------
总结一下类厂和组件的创建过程
类厂创建过程:
1. 在*_Server.cpp 中定义CComModule _Module 全局变量和一个数组,里面填入组件创建的相关函数信息
- CComModule _Module;
- BEGIN_OBJECT_MAP(ObjectMap)
- OBJECT_ENTRY(CLSID_Math, CMath)
- END_OBJECT_MAP()
2. Dll 加载时完成_Module的初始化
- BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID )
- {
- if (dwReason == DLL_PROCESS_ATTACH)
- {
- _Module.Init(ObjectMap, hInstance);
- }
- }
- inline HRESULT CComModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE , const GUID* plibid) throw()
- {
- m_pObjMap = p;
- //......
- }
3. 用户调用 CoCreateInstance 时,dll导出函数 DllGetClassObject 会被调用
- STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
- {
- return _Module.GetClassObject(rclsid, riid, ppv);
- }
- //rclsid = CLSID_Math
- inline HRESULT CComModule::GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw()
- {//......
- _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap;
- while (pEntry->pclsid != NULL)
- {
- if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid))
- {
- //pEntry->pfnGetClassObject == CMath::_ClassFactoryCreatorClass::CreateInstance
- //pEntry->pfnCreateInstance == CMath::_CreatorClass::CreateInstance
- hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF);
- break;
- }
- pEntry++;
- }
- }
4. DllGetClassObject 会导致 CMath::_ClassFactoryCreatorClass::CreateInstance 的调用
- CMath::_ClassFactoryCreatorClass 类型是 CComCreator, 也就是 CComCreator::CreateInstance 被调用,创建了类厂
- //typedef ATL::CComCreator< ATL::CComObjectCached< ATL::CComClassFactory > > _ClassFactoryCreatorClass;
- template <class T1> //T1 = ATL::CComObjectCached< ATL::CComClassFactory > 类厂
- class CComCreator
- {//......
- static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
- {
- *ppv = NULL;
- HRESULT hRes = E_OUTOFMEMORY;
- T1* p = new T1(pv)); //这里创建了类厂
- if (p != NULL)
- {
- p->SetVoid(pv); //pv = CMath::_CreatorClass::CreateInstance
- p->QueryInterface(riid, ppv); //获取组件接口指针
- //......
- }
- }
- };
*********************************************************************************
组件的创建过程:
1. CComCreator::CreateInstance 创建类厂后,会调用 SetVoid(pv) 将组件创建的函数指针创给了类工厂
- class CComClassFactory : //.....
- {//.....
- void SetVoid(void* pv) //pv = CMath::_CreatorClass::CreateInstance
- {
- m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;
- }
- _ATL_CREATORFUNC* m_pfnCreateInstance;
- };
2. 用户调用的 CoCreateInstance, 在成功创建类厂后,会调用类厂的 CreateInstance接口
- class CComClassFactory : //.....
- {//.....
- STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
- {
- HRESULT hRes = E_POINTER;
- *ppvObj = NULL;
- if ((pUnkOuter != NULL) && !InlineIsEqualUnknown(riid)) //检查参数
- {
- ATLTRACE(atlTraceCOM, 0, _T("CComClassFactory: asked for non IUnknown interface while creating an aggregated object"));
- hRes = CLASS_E_NOAGGREGATION;
- }
- else
- hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj); //调用组件创建函数
- return hRes;
- }
- _ATL_CREATORFUNC* m_pfnCreateInstance; //m_pfnCreateInstance = CMath::_CreatorClass::CreateInstance
- };
3. 类厂的 CreateInstance 会调用通过 SetVoid 获取的组件创建的函数指针, 也就是CMath::_CreatorClass::CreateInstance
- //typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< CMath > >, ATL::CComCreator< ATL::CComAggObject< CMath > > > _CreatorClass;
- template <class T1, class T2> //T1 = ATL::CComCreator< ATL::CComObject< CMath > >, T2 = ATL::CComCreator< ATL::CComAggObject< CMath > >
- class CComCreator2
- {
- public:
- static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
- {
- ATLASSERT(ppv != NULL);
- return (pv == NULL) ?
- ATL::CComCreator< ATL::CComObject< CMath > >::CreateInstance(NULL, riid, ppv) :
- ATL::CComCreator< ATL::CComAggObject< CMath > >::CreateInstance(pv, riid, ppv);
- }
- };
4. CComCreator2 会通过检查pv参数,确定是创建组合对象还是非组合对象,最终还是通过 CComCreator 创建组件
- //ATL::CComCreator< ATL::CComObject< CMath > >::CreateInstance(NULL, riid, ppv);
- template <class T1> //T1 = ATL::CComCreator< ATL::CComObject< CMath > > 或 ATL::CComCreator< ATL::CComAggObject< CMath > > 创建组件
- class CComCreator
- {//.....
- static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
- {
- *ppv = NULL;
- HRESULT hRes = E_OUTOFMEMORY;
- //ATL::CComObject< CMath > *p = new ATL::CComObject< CMath > (pv);
- T1* p = new T1(pv)); //这里创建了组件或类厂
- //.....
- hRes = p->QueryInterface(riid, ppv); //获取组件接口指针
- return hRes;
- }
- };
到此,组件创建完成。
http://blog.csdn.net/hongjiqin/article/details/4460095
- 通过ATL实现类厂和组件的创建
- 通过ATL开发COM_3实现类厂和组件的创建
- ATL是怎么创建类厂的
- 数据库操作组件的ATL实现
- 通过ATL COM组件实现在RichEdit中各种图片的显示(包括Gif图片的显示)
- ATL 8.0(VS2005) 我要创建一个继承自多个接口的组件类
- VS2005 创建的ATL工程无法注册组件
- 在用ATL创建组件时,如何在一个接口的实现中创建另一个已经实现了的接口的对象?
- ATL--创建简单的ATL之dll工程,添加类和类的接口并在MFC中调用
- ATL--创建简单的ATL之dll工程,添加“ATL简单对象”类的参数说明
- 通过ATL实现IUnknown接口
- 用ATL创建COM组件(详细分析了ATL创建的各种文件的意义,看完之后ATL就入门了)
- 通过继承Thread类和通过实现Runnable接口 创建线程的区别
- 用ATL创建COM组件详细解说
- vs2010 用ATL创建com组件
- 用ATL创建COM组件详细解说
- 用ATL创建COM组件详细解说
- 用ATL创建COM组件详细解说
- struts2转向之通配符,转向结果使用动态值
- 【cocos2d-x入门实战】微信飞机大战之十三:游戏场景过渡
- 嵌套的 CONTAINING_RECORD 宏
- ANT构建JAR包时设置MANIFEST.MF的Class-Path属性的技巧
- CoInternetIsFeatureEnabledForUrl
- 通过ATL实现类厂和组件的创建
- POJ1517u Calculate e
- 今天一同事买了变形金刚笑死我了
- 有没有人有kindle的电子书,大家可以共享一下,或是低价买卖一下也可以啊
- 齐鲁工业大学CSDN高校俱乐部“行走中的技术”成功举办
- ※数据结构※→☆非线性结构(tree)☆============二叉树 链式存储结构(tree binary list)(二十一)
- C#中ToString格式大全
- struts2源码分析(二)(初始化)
- 对于分录设置排序