以后将分别介绍ATL中各个形式为COM_INTERFACE_ENTRY_XX的接口映射宏并将按照从易到难的顺序讲解,每一部分都将建立在前一部分的基础上。每一部分都将通过分析实际的调用函数堆栈来进行分析,堆栈的写法是从下向上。文中所涉及的代码都为略写,只列出相关部分。
一、COM_INTERFACE_ENTRY(x)
首先我们从一个最典型的应用开始:
定义一个最简单的ATL DLL:
class ATL_NO_VTABLE CMyObject :
public CComObjectRootEx,
public CComCoClass,
public IDispatchImpl
{
.....
BEGIN_COM_MAP(CMyObject)
COM_INTERFACE_ENTRY(IMyObject) //一个双接口
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
.....
};
编写一段最简单的查询接口代码:
IUnknown *pUnk;
IMyObject *pMyObject;
CoCreateInstance(CLSID_MyObject, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnk);
pUnk->QueryInterface(IID_IMyObject, (void **)&pMyObject);
执行客户代码,首先我们看看组件对象是如何被创建的。
函数调用堆栈一:
4...........
3.ATL::CComCreator< ATL::CComObject< CMyObject > >::CreateInstance(...)
2.ATL::CComCreator2< ATL::CComCreator< ATL::CComObject< CMyObject > >,
ATL::CComCreator< ATL::CComAggObject< CMyObject > > >::CreateInstance(...)
1.ATL::CComClassFactory::CreateInstance(...)
4.ATL::AtlModuleGetClassObject(...)
9.ATL::AtlInternalQueryInterface(...)
8.ATL::CComObjectRootBase::InternalQueryInterface(...)
7.ATL::CComClassFactory::_InternalQueryInterface(...)
6.ATL::CComObjectCached::QueryInterface(...)
5.ATL::CComCreator >::
CreateInstance(...)
4.ATL::AtlModuleGetClassObject(...)
3.ATL::CComModule::GetClassObject(...)
2.DllGetClassObject(...)
1.CoCreateInstance(...)(客户端)
解释如下:
1:
CoCreateInstance(CLSID_MyObject, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnk);
其内部将调用OLE API函数CoGetClassObject(), 而CoGetClassObject则会通过 LoadLibrary(...)装入DLL,并调用DLL中的DllGetClassObject()函数。