2006 年 11 月 23 日 23 時 37 分

IClassFactory インタフェース


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


クラスオブジェクトは、その一般的な機能を提供するために、
IClassFactory インタフェースを実装することが推奨される。

IClassFactory の定義を以下に示す。

class IClassFactory : public IUnknown {

public:

    virtual HRESULT STDMETHODCALLTYPE CreateInstance(
            /* [in] */ IUnknown* pUnkOuter,
            /* [in] */ REFIID riid,
            /* [out] */ void** ppvObject) = 0;

    virtual HRESULT STDMETHODCALLTYPE LockServer(
            /* [in] */ BOOL fLock) = 0;

};

IClassFactory はクラスオブジェクトの基本機能を表す。
例によって IClassFactory も IUnknown を継承している。

CreateInstance はクラスの新しいインスタンスを作成する。
riid、ppvObject は毎度お決まりの引数であり、
このメソッドがインスタンス生成の核となる。

pUnkOuter 引数は CoCreateInstance の引数と同じで、
基本的に NULL と考えておいて構わない。

COM の集約という機能が要求された場合は NULL でないが、
集約の実装は任意であるため、NULL でない場合は、
CLASS_E_NOAGGREGATION というエラーを返すことができる。

このメソッドは固有のパラメータを持たないので、
作成されたインスタンスは「未初期化の状態」となる。
そのため、原則としてインスタンスの初期化は、
別途メソッドを呼び出して行うことになっている。

LockServer メソッドは、オブジェクト利用の効率化のため、
COM サーバをロックし、アンロードを防ぐ機能を持つ。

通常、サーバが提供しているインスタンスを、
クライアントが全て解放すると、
サーバはアンロードされる。

インプロセスサーバの場合、サーバのロードやアンロードは
COM 基盤によって行われるが、COM 基盤側は
生きたインスタンスの数や参照を監視していないので、
COM 基盤がサーバに対して定期的に確認を行うために、
DLL に実装された DllCanUnloadNow という関数を呼ぶ。

DllCanUnloadNow は以下のようなプロトタイプを持つ。
実は、この関数もインプロセスサーバが提供する必要がある。

STDAPI DllCanUnloadNow(void);

この関数は、S_OK か S_FALSE を返すことになっている。
アンロードが可能であれば S_OK を返す。

通常、サーバはインスタンスの参照カウンタを持っており、
その数を調べることでアンロードの可否を返す。

一般的にはこれで構わないが、
インスタンスを生成してすぐに解放するような処理を、
定期的に行うようなクライアントでは、
サーバのロードとアンロードが頻繁に行われる心配がある。

その際に、自動的なサーバのアンロードを抑止し、
インスタンスの生成と破棄を効率よく行う事ができるように、
IClassFactory に、LockServer メソッドがあるのだ。

クライアントが fLock 引数に TRUE を渡して
LockServer メソッドを呼び出すと、
サーバは DllCanUnloadNow に S_FALSE を返すようになる。
これによりクライアントがサーバをロックすることができる。

クライアントが fLock 引数に FALSE を渡して
LockServer メソッドを呼び出すと、
サーバのロックは解除される。

LockServer メソッドは繰り返し呼ばれる可能性があるので、
サーバは LockServer の呼び出し回数を管理する必要がある。

つまり、サーバは自身の提供するインスタンスの参照の数と、
LockServer のロック回数を管理しなければならないのだ。



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