ファクトリ テンプレートの配列
ファクトリ テンプレートは、次のパブリック メンバ変数を格納する。
const WCHAR * m_Name; // 名前。
const CLSID * m_ClsID; // CLSID。
LPFNNewCOMObject m_lpfnNew; // コンポーネントの
// インスタンスを作成する関数。
LPFNInitRoutine m_lpfnInit; // 初期化関数 (省略可能)。
const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter; // セットアップ情報 (フィルタ用)。
2 つの関数ポインタ m_lpfnNew および m_lpfnInit は、次の型定義を使う。
typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
1 番目の定義は、コンポーネントのインスタンス化関数である。2 番目の定義は、オプションの初期化関数である。初期化関数を指定した場合、関数は DLL エントリ ポイント関数内部から呼び出される。(DLL エントリ ポイント関数については、後のセクションで説明する)。
たとえば CUnknown から継承した CMyComponent という名前のコンポーネントを含む DLL を作成するとする。この場合、次の項目を DLL に提供しなければならない。
- 初期化関数。CMyComponent の新しいインスタンスを返すパブリック メソッド。
- g_Templates という名前のファクトリ テンプレートのグローバル配列。この配列は、CMyComponent のファクトリ テンプレートを格納する。
- 配列のサイズを指定する g_cTemplates という名前のグローバル変数。
これらの項目を宣言する例を次に示す。
// 新しいインスタンスを返すパブリック メソッド。
CUnknown * WINAPI CMyComponent::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
{
CMyComponent *pNewObject = new CMyComponent(NAME("My Component"), pUnk, pHr );
if (pNewObject == NULL) {
*pHr = E_OUTOFMEMORY;
}
return pNewObject;
}
CFactoryTemplate g_Templates[1] =
{
{
L"My Component", // 名前。
&CLSID_MyComponent, // CLSID。
CMyComponent::CreateInstance, // MyComponent のインスタンスを作成するメソッド。
NULL, // 初期化関数。
NULL // セットアップ情報 (フィルタ用)。
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
CreateInstance メソッドは、クラス コンストラクタを呼び出して新しいクラス インスタンスへのポインタを返す。パラメータ pUnk は、集成化 IUnknown へのポインタである。このパラメータをクラス コンストラクタに渡す。パラメータ pHr は、HRESULT 値へのポインタである。クラス コンストラクタはこれを適切な値に設定する。ただしコンストラクタが失敗した場合は、値を E_OUTOFMEMORY に設定する。
NAME マクロは、デバッグ ビルドにおいて文字列を生成するが、リテール ビルドでは NULL に解決する。この例でコンポーネントに与えられている名前は、デバッグ ログには記録されるが、最終バージョンではメモリを占有しない。
クラス ファクトリはファクトリ テンプレートの関数ポインタを参照するため、CreateInstance メソッドは任意の名前を持てる。ただし、g_Templates と g_cTemplates は、クラス ファクトリが期待するグローバル変数なので、必ずこの名前を持たなければならない。