次の方法で共有


ファクトリ テンプレートの配列

ファクトリ テンプレートは、次のパブリック メンバ変数を格納する。

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_Templatesg_cTemplates は、クラス ファクトリが期待するグローバル変数なので、必ずこの名前を持たなければならない。