ATLにおけるプロセス内サーバ登録メカニズムの変更


一、ATL 3.0では、オブジェクトマッピングテーブルによってサーバを登録する.BEGIN_OBJECT_MAP(ObjectMap)
   OBJECT_ENTRY(CLSID_MyCircleCollectionCreator, CMyCircleCollectionCreator)
     
END_OBJECT_MAP( )
     

ATLがサーバを登録すると、最終的にAtlModuleRegisterServer関数に呼び出されてサーバ登録が行われます.コンポーネントがサポートするすべてのオブジェクトについて、レジストリ・アイテムを作成して登録し、登録プロセスが終了します.
 
しかし、ATL 7では、以上の3つのマクロが時代遅れになり、代わりにマクロOBJECT_ENTRY_AUTO.次にマクロOBJECTを解析します.ENTRY_AUTOの実現.
 
二、マクロOBJECT_ENTRY_AUTOの定義.
1.     まず見てみましょうATL_OBJMAP_ENTRYの定義:
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;
};
typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY;
 
2.     マクロOBJECT_ENTRY_AUTOの定義は以下の通りです.
#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)
3.     次に、補助マクロOBJECTを見てみましょう.ENTRY_PRAGMAは、以下のように定義されています.
#define OBJECT_ENTRY_PRAGMA(class)/
 __pragma(comment(linker, "/include:___pobjMap_"#class));
 
三、マクロOBJECT_ENTRY_AUTOの機能
1.     構造体_ATL_OBJMAP_ENTRYはもちろんATL 3と全く同じです.
2.     マクロOBJECT_ENTRY_AUTOの機能:
1)     clsid,classの情報を用いて_を生成するATL_OBJMAP_ENTRYのインスタンスです.変数名は__です.objMap_classの実績値を加算します.
2)     宣言1)生成されたインスタンスのポインタであり、1)生成されたインスタンスのアドレスを割り当てます.でもポインタはATL$_に置かれていますmセグメントです.
3.     マクロOBJECT_ENTRY_PRAGMAの機能は、コネクタにシンボルテーブルにシンボルを追加するように伝えることです_objMap_classの実績値を加算します.注意:X 86プラットフォームの下で、記号名が宣言された名前の前に下線を引きます.だからOBJECTでENTRY_PRAGMAマクロでは、pobjMapの前に下線が3つあります.
四、どの部分のコードの中でOBJECTを使うかENTRY_AUTO
ATL 7.0プロジェクトの作成時:
1.       非属性化プログラミングを使用している場合は、COMクラスのヘッダファイルでウィザードによって自動的に生成されます.マクロを削除しないでください.そうしないと、クラスのインスタンスを作成できません.このような間違いはまた発見しにくい.
2.       属性化プログラミングを使用している場合、COMクラスの前にcoclass属性があり、コンパイラはコードにいくつかのコードを挿入して以下の機能を完了します.
l         COMクラスのベースクラスを追加
l         登録コードの生成
l         インタフェースマッピングテーブルの生成
l         オブジェクトマッピングアイテム、すなわちマクロOBJECT_を生成ENTRY_AUTO
コードではOBJECTは実際には見えませんENTRY_AUTO.
五、OBJECT_ENTRY_AUTOはシステムの他の部分と協力して、ここでオブジェクトマッピングテーブルの確立と使用を分析します.
非属性化プログラミングを使用すると、ユーザーは任意の合法的なCOMクラス名を生成することができる.属性化プログラミングを使用すると、私たちは全然知りません.ATL_OBJMAP_ENTRYポインタ変数の名前は、ATLライブラリにとって、ユーザ定義のCOMクラスの名前を予め知ることはできません.では、レジストリの更新を行うには、オブジェクトマッピングテーブルをどのように巡回しますか?
答えは、オブジェクトマッピングテーブルの作成です.まず、マッピングテーブルの開始項目、終了項目を見てみましょう.定義は次のとおりです.
__declspec(selectany) __declspec(allocate("ATL$__a")) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL;
__declspec(selectany) __declspec(allocate("ATL$__z")) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL;
次のように分析されます.
l         注意が必要なのは、_pobjMapEntryFirst、__pobjMapEntryLastは、セグメントATL$_にそれぞれ配置されるaとATL$zで.
l                 もう一度注意したいのは、マクロOBJECT_を介してENTRY_AUTOに配置された変数はATL$m中.
l         コネクタがコードをレイアウトすると、すべてのセグメントが名前に基づいてアルファベット順に並べられます.このようにセグメントATL$aの変数はセグメントATL$_に現れるzすべての変数の前.
l         最後に、#pragma comment(linker,"/merge:ATL=.rdata")を使用して、3つのセグメントのすべてのデータをセグメント.rdata読取り専用データセグメントにマージします.
l         最後に作成されるレイアウトは次のようになります.
__pobjMapEntryFirst

 
UserDefinedPtr1
UserDefinedPtr2

 
__pobjMapEntryLast
これにより,オブジェクトマッピングテーブルが形成される.ATLライブラリでは、__に基づいてpobjMapEntryFirst、__pobjMapEntryLastは、オブジェクトマッピングテーブルを特定し、その中のすべてのオブジェクトを登録します.