通过ATL实现类厂和组件的创建
2013-09-27 10:05
309 查看
类工厂的实现,组件的创建过程
1. 在*_Server.cpp 中有
[cpp]
view plaincopyprint?
BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_Math, CMath) END_OBJECT_MAP()
展开后是这样:
[cpp]
view plaincopyprint?
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 变量
[cpp]
view plaincopyprint?
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组件
[cpp]
view plaincopyprint?
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 创建类厂的
[cpp]
view plaincopyprint?
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 展开
[cpp]
view plaincopyprint?
//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 调用
[cpp]
view plaincopyprint?
//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 它的定义
[cpp]
view plaincopyprint?
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 会是如何实现创建组件实例
[cpp]
view plaincopyprint?
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 全局变量和一个数组,里面填入组件创建的相关函数信息
[cpp]
view plaincopyprint?
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_Math, CMath) END_OBJECT_MAP()
2. Dll 加载时完成_Module的初始化
[cpp]
view plaincopyprint?
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 会被调用
[cpp]
view plaincopyprint?
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 的调用
[cpp]
view plaincopyprint?
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) 将组件创建的函数指针创给了类工厂
[cpp]
view plaincopyprint?
class CComClassFactory : //..... {//..... void SetVoid(void* pv) //pv = CMath::_CreatorClass::CreateInstance { m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv; } _ATL_CREATORFUNC* m_pfnCreateInstance; };
2. 用户调用的 CoCreateInstance, 在成功创建类厂后,会调用类厂的 CreateInstance接口
[cpp]
view plaincopyprint?
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
[cpp]
view plaincopyprint?
//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 创建组件
[cpp]
view plaincopyprint?
//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; } };
到此,组件创建完成。
/article/9948068.html
1. 在*_Server.cpp 中有
[cpp]
view plaincopyprint?
BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_Math, CMath) END_OBJECT_MAP()
BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_Math, CMath) END_OBJECT_MAP()
展开后是这样:
[cpp]
view plaincopyprint?
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} };
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 变量
[cpp]
view plaincopyprint?
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++;
}
}
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组件
[cpp]
view plaincopyprint?
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++;
}
}
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 创建类厂的
[cpp]
view plaincopyprint?
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); } };
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 展开
[cpp]
view plaincopyprint?
//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; } };
//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 调用
[cpp]
view plaincopyprint?
//pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF); CMath::_ClassFactoryCreatorClass::CreateInstance (CMath::_CreatorClass::CreateInstance, __uuidof(IUnknown), (LPVOID*)NULL);
//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 它的定义
[cpp]
view plaincopyprint?
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; };
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 会是如何实现创建组件实例
[cpp]
view plaincopyprint?
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); } };
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 全局变量和一个数组,里面填入组件创建的相关函数信息
[cpp]
view plaincopyprint?
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_Math, CMath) END_OBJECT_MAP()
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_Math, CMath) END_OBJECT_MAP()
2. Dll 加载时完成_Module的初始化
[cpp]
view plaincopyprint?
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; //...... }
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 会被调用
[cpp]
view plaincopyprint?
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++;
}
}
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 的调用
[cpp]
view plaincopyprint?
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); //获取组件接口指针 //...... } } };
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) 将组件创建的函数指针创给了类工厂
[cpp]
view plaincopyprint?
class CComClassFactory : //..... {//..... void SetVoid(void* pv) //pv = CMath::_CreatorClass::CreateInstance { m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv; } _ATL_CREATORFUNC* m_pfnCreateInstance; };
class CComClassFactory : //..... {//..... void SetVoid(void* pv) //pv = CMath::_CreatorClass::CreateInstance { m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv; } _ATL_CREATORFUNC* m_pfnCreateInstance; };
2. 用户调用的 CoCreateInstance, 在成功创建类厂后,会调用类厂的 CreateInstance接口
[cpp]
view plaincopyprint?
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 };
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
[cpp]
view plaincopyprint?
//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); } };
//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 创建组件
[cpp]
view plaincopyprint?
//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; } };
//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; } };
到此,组件创建完成。
/article/9948068.html
相关文章推荐
- 通过ATL开发COM_3实现类厂和组件的创建
- 程序通过创建线程实现删除自身
- 通过字符串调用方法得到结果及动态创建Swing组件和布局
- 组件对象模型与ATL实现
- C#通过引用Office Excel (2007) 组件实现对Excel文件的操作
- 通过创建SQL Server 2005到 Oracle10g 的链接服务器实现异构数据库数据转换方案
- 自己搭建自动化巡检系统(三) 通过telnet实现远程创建loopback
- C#如何使用反射实现通过字符串创建类
- asp.net通过js实现Cookie创建以及清除Cookie数组的代码
- 通过实现继承TabActivity并且实现TabContentFactory的方法创建选项卡的一点心得
- C# 反射-通过继承接口实现创建对象并调用方法
- COM笔记-组件的创建和类厂
- VS2005 创建的ATL工程无法注册组件
- C#通过引用Office Excel (2007) 组件实现对Excel文件的操作
- 【qtp脚本】实现自动创建目录并通过测试写字板生成指定个数的文件
- 【Android开发】线程与消息处理-通过实现Runnable接口来创建线程
- 重写hierarchy面板,实现创建Text自动添加content size fitter组件
- Windows Forms中通过自定义组件实现统一的数据验证(一)
- Windows Forms中通过自定义组件实现统一的数据验证(一)
- 使用VC++/ATL创建一个Office2K AddIn Com 组件