2006 年 11 月 22 日 23 時 54 分

サーバから見たインスタンスの作成


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


インプロセスサーバがクラスを提供するためには、
DLL に DllGetClassObject 関数を実装する必要がある。
この関数は以下のようなプロトタイプを持っている。

STDAPI DllGetClassObject(
        /* [in] */ REFCLSID rclsid,
        /* [in] */ REFIID riid,
        /* [out] */ void** ppvObject);

rclsid はクラスの ID、riid はインタフェースの ID、
そして、ppvObject にはクラスのインスタンスを返す。

これが DllCreateInstance という名前でない事に注意。
この関数は、クラスのインスタンスを作成するのではなく、
ppvObject に「クラスオブジェクト」を返す必要がある。

クラスオブジェクトとは、クラス自身を表すクラスの
インスタンスで、メタクラスとも呼ばれることがある。
これは Java の Class クラス、C# の Type クラスに近く、
インスタンスの生成を主とするファクトリの機能を持つ。

COM では、コンストラクタを使った初期化は行わないので、
クラスオブジェクトがインスタンスの生成と初期化を制御し、
柔軟性を持たせる事ができるようになっている。

クラスオブジェクトも、COM クラスのインスタンスなので、
他の COM クラス同様 IUnknown を実装している。
そのため、DllGetClassObject の引数には、
毎度お決まりのインタフェース ID が必要となっている。

処理を効率化するため、DllGetClassObject は、
呼び出し毎に新しいインスタンスを返す必要はない。
そのため、クラスオブジェクトは参照カウンタを無視し、
インスタンスが常にメモリ上に存在するように、
シングルトンとして実装することが推奨される。

さて、クライアントが CoCreateInstance を呼び出すと、
COM 基盤がサーバに対してインスタンスの生成を要求する。
これは、以下のような擬似的なコードに相当する。

    // クラスオブジェクトの IClassFactory を取得
    IClassFactory* factory = NULL;
    DllGetClassObject(CLSID_XXXX,
            IID_IClassFactory, (void**)&factory);

    // インスタンスを生成(引数は一例)
    IUnknown *instance = NULL;
    factory->CreateInstance(NULL,
            IID_IUnknown, (void**)&instance);

    // クラスオブジェクトを解放
    factory->Release();

本来、クラスオブジェクトの実装は自由裁量なのだが、
クライアントの利便性とインスタンス生成の共通化のため、
IClassFactory インタフェースを実装することが推奨される。

CoCreateInstance を使うクライアントに対応するためには、
IClassFactory の実装は必須である。
IClassFactory は、CreateInstance というメソッドを持ち、
汎用的・一般的なインスタンス作成の機能を提供する。

サーバがクラスを提供するためには、
クラスオブジェクトを用意する必要があるのだ。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.