您的位置:首页 > 移动开发 > Objective-C

ATL Internals 2ed复习.chapter 5.Object Map

2012-10-07 12:11 330 查看

由于有3种COM Server,ATL提供了CAtlModule的派生类对应

CAtlDllModuleT:in-process dll

CAtlExeModuleT:out-process exe

CAtlServiceModuleT:system service exe

CAtlModule使用了Object Map管理server中所有的类

CAtlModule的职责

找到每个class,注册/反注册

为每个createable class创建class object

在SCM中注册/反注册class object

为一个class查找component categories

调用class的静态初始化和静态终结函数

注册Server

Inproc Server Registration

template <class T>
class ATL_NO_VTABLE CAtlDllModuleT : public CAtlModuleT<T> {
public:
...
HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) {
...
T* pT = static_cast<T*>(this);
HRESULT hr = pT->RegisterAppId(); // execute server script
...
return hr;
}
...
};




Local Server and Windows Service Registration

template <class T>
class CAtlExeModuleT : public CAtlModuleT<T> {
public :

int WinMain(int nShowCmd) throw() {
...
HRESULT hr = S_OK;

LPTSTR lpCmdLine = GetCommandLine();
if (pT->ParseCommandLine(lpCmdLine, &hr) == true)
hr = pT->Run(nShowCmd);

...
}

bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) {
*pnRetCode = S_OK;

TCHAR szTokens[] = _T("-/");

T* pT = static_cast<T*>(this);
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
while (lpszToken != NULL) {
if (WordCmpI(lpszToken, _T("UnregServer"))==0) {
*pnRetCode = pT->UnregisterServer(TRUE); // server script
if (SUCCEEDED(*pnRetCode))
*pnRetCode = pT->UnregisterAppId(); // all class scripts
return false;
}

// Register as Local Server
if (WordCmpI(lpszToken, _T("RegServer"))==0) {
*pnRetCode = pT->RegisterAppId(); // server script
if (SUCCEEDED(*pnRetCode))
*pnRetCode = pT->RegisterServer(TRUE); // all class scripts
return false;
}

lpszToken = FindOneOf(lpszToken, szTokens);
}

return true;
}
};


The Object Map

每一个createable class都类似:

class CMyClass : public CComCoClass< ... >, ...
{
public:

...
};

OBJECT_ENTRY_AUTO(__uuidof(MyClass), CMyClass)	//第一个参数是clsid


在ATL3中,我们使用BEGIN_OBJECT_MAP和END_OBJECT_MAP,到了ATL7之后不再需要了。

_ATL_OBJMAP_ENTRY Structure

Object Map就是一个_ATL_OBJMAP_ENTRY的数组:

struct _ATL_OBJMAP_ENTRY30 {
const CLSID* pclsid;                                //CLSID
HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister);//用于注册
_ATL_CREATORFUNC* pfnGetClassObject;                //用于创建class object
_ATL_CREATORFUNC* pfnCreateInstance;                //用于创建instance
IUnknown* pCF;                                      //class object的IUnknown*
DWORD dwRegister;                                   //CoRegisterClassObject的cookie返回
_ATL_DESCRIPTIONFUNC* pfnGetObjectDescription;      //用于返回object description
_ATL_CATMAPFUNC* pfnGetCategoryMap;                 //用于component category
void (WINAPI *pfnObjectMain)(bool bStarting);       //initilization/termination function
};

typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY;


OBJECT_ENTRY_AUTO Macro

当我们使用这个宏来指定COM-createable class,默认情况下这个类需要派生自CComCoClass,然后用户可以使用CoCreateInstance()来创建它们

OBJECT_ENTRY_NON_CREATEABLE_EX_AUTO macro

使用这个宏用于noncreateable class,如果这个类需要class-level initialization/termination或者在注册表注册

Methods Required of an Object Map Class

为了支持Object Map,用户需要提供下列函数:

Static Member Function
Description
UpdateRegistry
Registers and unregisters the class. The DECLARE_REGISTRY_RESOURCE macros provide various implementations of this method for nonattributed projects. Attributed projects have an implementation injected by the attribute provider.
ObjectMain
Initializes and uninitializes the class. CComObjectRootBase provides a default implementation of this method.
GetCategoryMap
Returns a pointer to a component category map. The BEGIN_CATEGORY_MAP macro provides an implementation.CComObjectRootBase provides a default implementation of this method.
CreatorClass::CreateInstance
_The DECLARE_AGGREGATABLE macros set the
_CreatorClass typedef to the name of the class that creates instances. CComCoClass provides a default definition of this typedef.
_ClassFactoryCreatorClass:: CreateInstance
The DECLARE_CLASSFACTORY macros set the _ClassFactoryCreatorClass typedef to the name of the class that creates class objects.CComCoClass provides a default definition of this typedef.
GetObjectDescription
Returns the object description text string. CComCoClass provides a default implementation of this method.
其中前三条不管使用OBJECT_ENTRY_NON_CREATEABLE_EX_AUTO还是OBJECT_ENTRY_AUTO都必须提供

使用OBJECT_ENTRY_AUTO必须提供所有

The GetObjectDescription Method

使用DECLARE_OBJECT_DESCRIPTION macro,例如:

class CMyClass : public CComCoClass< ... >, ... {
public:
DECLARE_OBJECT_DESCRIPTION("MyClass Object Description")

...
};




The UpdateRegistry Method

class必须提供一个静态函数:

static HRESULT WINAPI UpdateRegistry(BOOL bRegister) ;


可以使用DECLARE_REGISTRY:

#define DECLARE_NO_REGISTRY()\
static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) \
{return S_OK;}

#define DECLARE_REGISTRY(class, pid, vpid, nid, flags)\
static HRESULT WINAPI UpdateRegistry(BOOL bRegister) {\
return _Module.UpdateRegistryClass(GetObjectCLSID(), \
pid, vpid, nid,\
flags, bRegister);\
}

#define DECLARE_REGISTRY_RESOURCE(x)\
static HRESULT WINAPI UpdateRegistry(BOOL bRegister) {\
...
return ATL::_pAtlModule->UpdateRegistryFromResource(_T(#x), \
bRegister); \
...
}

#define DECLARE_REGISTRY_RESOURCEID(x)\
static HRESULT WINAPI UpdateRegistry(BOOL bRegister) {\
...
return ATL::_pAtlModule->UpdateRegistryFromResource(x, \
bRegister); \
...
}


注意,DECLARE_REGISTRY只能在ATL3中使用,在ATL7+版本将会出现编译错误

如果使用DECLARE_REGISTRY_RESOURCE或者使用DECLARE_REGISTRY_RESOURCEID,需要指定脚本,详见原书

The GetCategoryMap Method

需要一个静态函数:

static const struct _ATL_CATMAP_ENTRY* GetCategoryMap() { return NULL; }


通常可以使用宏来解决,例如:

// {0D22FF22-28CC-11d2-ABDD-00A0C9C8E50D}
static const GUID CATID_ATLINTERNALS_SAMPLES =
{0xd22ff22, 0x28cc, 0x11d2, {0xab, 0xdd, 0x0, 0xa0, 0xc9, 0xc8,
0xe5, 0xd}};

BEGIN_CATEGORY_MAP(CDemagogue)
IMPLEMENTED_CATEGORY(CATID_ATLINTERNALS_SAMPLES)
END_CATEGORY_MAP()


这3个宏详见原书

The ObjectMain Method

需要一个静态函数:

static void WINAPI ObjectMain(bool /* bStarting */ ) {};


例如:

class ATL_NO_VTABLE CSoapBox :
public CComObjectRootEx<CComSingleThreadModel>,
...
{
public:
DECLARE_NO_REGISTRY()
...
static void WINAPI ObjectMain(bool bStarting) ;
};


The _ClassFactoryCreatorClass and _CreatorClass Typedefs

OBJECT_ENTRY_AUTO中

class::_ClassFactoryCreatorClass::CreateInstance用于创建class object

class::_CreatorClass::CreateInstance用于创建instance

在CComCoClass中,有_ClassFactoryCreatorClass定义:

template <class T, const CLSID* pclsid = &CLSID_NULL>
class CComCoClass {
public:
DECLARE_CLASSFACTORY()
DECLARE_AGGREGATABLE(T)
...
};


其中:

#define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
1
#if defined(_WINDLL) | defined(_USRDLL)
#define DECLARE_CLASSFACTORY_EX(cf) \
typedef ATL::CComCreator< \
ATL::CComObjectCached< cf > > _ClassFactoryCreatorClass;
#else
// don't let class factory refcount influence lock count
#define DECLARE_CLASSFACTORY_EX(cf) \
typedef ATL::CComCreator< \
ATL::CComObjectNoLock< cf > > _ClassFactoryCreatorClass;
#endif


上面的代码,当使用inproc dll时,CComCreator创建一个CComObjectCached<>作为cf,当使用exe时,创建一个CComObjectNoLock<>作为cf

而其中的CComClassFactory定义如下:

class CComClassFactory :
public IClassFactory,
public CComObjectRootEx<CComGlobalsThreadModel> {
public:
...
void SetVoid(void* pv) { m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;}
_ATL_CREATORFUNC* m_pfnCreateInstance;
};


上面SetVoid重载了CComObjectRootBase中的定义
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: