このアーカイブは同期化されません。 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 のロック回数を管理しなければならないのだ。