对象映射图:
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_Math, CMath)
END_OBJECT_MAP()
其中OBJECT_ENTRY映射为--->
#define OBJECT_ENTRY(clsid, class) {
&clsid, class::UpdateRegistry,
class::_ClassFactoryCreatorClass::CreateInstance, ----组件类厂创建
class::_CreatorClass::CreateInstance, ----组件实例创建
NULL,
0,
class::GetObjectDescription,
class::GetCategoryMap,
class::ObjectMain
},
其中的_ClassFactoryCreatorClass和_CreatorClass定义如下(都为创建类--CComCreator):
#define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator< ATL::CComObjectCached< cf > >_ClassFactoryCreatorClass;
#define DECLARE_AGGREGATABLE(x) public:/
typedef ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< x > >, ATL::CComCreator< ATL::CComAggObject< x > > > _CreatorClass;
CComCreator:
template <class T1>
class CComCreator
{
public:
static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
{
ATLASSERT(ppv != NULL);
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
HRESULT hRes = E_OUTOFMEMORY;
T1* p = NULL;
#pragma warning(push)
#pragma warning(disable: 6014)
/* prefast noise VSW 489981 */
ATLTRY(p = new T1(pv))
#pragma warning(pop)
if (p != NULL)
{
p->SetVoid(pv);
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;
}
};
当一个客户程序调用CoCreateInstanses时,COM将调哟DllGetClassObject。COM对DllGetClassObject
的调用最终会导致对AtlModuleGetClassObject的调用,而AtlModuleGetClassObject函数将在对象
映射图里搜索CLSID_Math条目。当函数找到它之后,AtlModuleGetClassObject将调用
&CMath::_ClassFactoryCreatorClass::CreateInstance并把&CMath::_CreatorClass::CreateInstance
作为参数传递进去。该参数被CComClassFactory里的m_pfmCreateInstance成员捕获。
CComClassFactory :
class CComClassFactory :
public IClassFactory,
public CComObjectRootEx<CComGlobalsThreadModel>
{
public:
BEGIN_COM_MAP(CComClassFactory)
COM_INTERFACE_ENTRY(IClassFactory)
END_COM_MAP()
// This will be made virtual again for Beta 2
/*virtual*/ ~CComClassFactory()
{
}
// IClassFactory
STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj)
{
ATLASSUME(m_pfnCreateInstance != NULL);
HRESULT hRes = E_POINTER;
if (ppvObj != NULL)
{
*ppvObj = NULL;
// can't ask for anything other than IUnknown when aggregating
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;
}
STDMETHOD(LockServer)(BOOL fLock)
{
if (fLock)
_pAtlModule->Lock();
else
_pAtlModule->Unlock();
return S_OK;
}
// helper
void SetVoid(void* pv)
{
m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;
}
_ATL_CREATORFUNC* m_pfnCreateInstance;
};
COM(通过CoCreateInstance)或客户程序(CoGetClassObject/CreateInstance)使用
CComClassFactory::CreateInstance来创建组件的实例。该函数实际调用m_pfmCreateInstance并把
pUnkOuter作为参数传递回去。如果pUnkOuter为空,表明客户程序没有进行集合,并且
CComCreator<CComObject<CMath>>::CreateInstance方法被使用。如果pUnkOuter不为空,那么
则表明生成了一个集合,并且使用了CComCreator<CComAggObject<CMath>>::CreateInstance方法。
CComCreator2:
template <class T1, class T2>
class CComCreator2
{
public:
static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
{
ATLASSERT(ppv != NULL);
return (pv == NULL) ?
T1::CreateInstance(NULL, riid, ppv) :
T2::CreateInstance(pv, riid, ppv);
}
};