代码改变世界

ATL 对象映射表

2012-11-01 23:46  Clingingboy  阅读(1203)  评论(0编辑  收藏  举报

 

一.作用

Each coclass adds an entry to the object map by allocating the _ATL_OBJMAP_ENTRY structure (discussed in detail shortly) within that same data segment. This produces a series of _ATL_OBJMAP_ENTRY structures that are contiguous in memory and, thus, can easily be iterated over by CAtlModule when it needs to perform registration, class object creation, and other class-management services.

二.添加方法

Each class inserts an item into the object map via the OBJECT_ENTRY_AUTO macro declared in the class header file outside the class declaration itself, as in the following:

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


   ...
};

OBJECT_ENTRY_AUTO(__uuidof(MyClass), CMyClass)

三._ATL_OBJMAP_ENTRY Structure

 
struct _ATL_OBJMAP_ENTRY30
{
    const CLSID* pclsid;
    HRESULT (WINAPI *pfnUpdateRegistry)(_In_ BOOL bRegister);
    _ATL_CREATORFUNC* pfnGetClassObject;
    _ATL_CREATORFUNC* pfnCreateInstance;
    IUnknown* pCF;
    DWORD dwRegister;
    _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription;
    _ATL_CATMAPFUNC* pfnGetCategoryMap;
    HRESULT WINAPI RevokeClassObject()
    {
        if (dwRegister == 0)
            return S_OK;
        return CoRevokeClassObject(dwRegister);
    }
    HRESULT WINAPI RegisterClassObject(
        _In_ DWORD dwClsContext,
        _In_ DWORD dwFlags)
    {
        IUnknown* p = NULL;
        if (pfnGetClassObject == NULL)
            return S_OK;
        HRESULT hRes = pfnGetClassObject(pfnCreateInstance, __uuidof(IUnknown), (LPVOID*) &p);
        if (SUCCEEDED(hRes))
            hRes = CoRegisterClassObject(*pclsid, p, dwClsContext, dwFlags, &dwRegister);
        if (p != NULL)
            p->Release();
        return hRes;
    }
// Added in ATL 3.0
    void (WINAPI *pfnObjectMain)(_In_ bool bStarting);
};

typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY;
 
介绍
image

四.OBJECT_ENTRY_AUTO Macro

You use the OBJECT_ENTRY_AUTO macro to specify a COM-createable class. Typically, this means the specified class derives from the CComCoClass base class. Often these are top-level objects in an object model. Clients typically create such top-level objects using CoCreateInstance.

#define OBJECT_ENTRY_AUTO(clsid, class) \
    __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }; \
    extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \
    OBJECT_ENTRY_PRAGMA(class)

知识背景

__declspec(selectany)的作用

c++ 中__declspec 的用法

理解这个宏是重点

#pragma section("ATL$__a", read)
#pragma section("ATL$__z", read)
#pragma section("ATL$__m", read)
extern "C"
{
__declspec(selectany) __declspec(allocate("ATL$__a")) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL;
__declspec(selectany) __declspec(allocate("ATL$__z")) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL;
}

The alphabetical order of sections in the resulting file is guaranteed through a special naming rule enforced by the linker

#define OBJECT_ENTRY(clsid, class) {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain },

如上面代码将会生成如下对象映射表

image