DirectShow は CUnknown と呼ばれる基底クラスの IUnknown を実装する。この CUnknown を使って他のクラスを派生し、コンポーネント間で変わるメソッドだけをオーバーライドできる。DirectShow の他の基底クラスのほとんどは CUnknown から派生するので、作成するコンポーネントを CUnknown または他の基底クラスから直接継承できる。
INonDelegatingUnknown
CUnknown は INonDelegatingUnknown を実装する。CUnknown は参照カウントを内部的に管理し、ほとんどの状況で派生クラスは同じ 2 つの参照カウント メソッドを実装する。CUnknown は参照カウントがゼロになるとそれ自体を削除する。その一方では、CUnknown::NonDelegatingQueryInterface をオーバーライドしなければならない。なぜなら、基底クラスのメソッドは IID_IUnknown 以外の IID を受け取ると E_NOINTERFACE を返すからである。派生クラスでは、次の例に示すようにサポートするインターフェイスの IID をテストする必要がある。
トップ10のコミュニティカレッジ専攻
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv) { if (riid == IID_ISomeInterface) { return GetInterface((ISomeInterface*)this, ppv); } // デフォルト。 return CUnknown::NonDelegatingQueryInterface(riid, ppv); }
ユーティリティ関数 GetInterface (「COM ヘルパー関数」を参照すること) はポインタを設定し、スレッドに対応した方法で参照カウントを実装し、S_OK を返す。デフォルトのケースでは、基底クラス メソッドを呼び出してその結果を返す。別の基底クラスから派生させた場合は、その NonDelegatingQueryInterface メソッドを代わりに呼び出す。これにより、親クラスがサポートするすべてのインターフェイスをサポートできる。
IUnknown
上述のように、IUnknown の委任バージョンは、非委任バージョンの正しいインスタンスを起動するだけなので、すべてのコンポーネントで同じである。便宜上、ヘッダー ファイル Combase.h は、インライン メソッドとして 3 つの委任メソッドを宣言するマクロ DECLARE_IUNKNOWN を含んでいる。このコードを次に示す。
労働組合機関アンペア大学どうすれば
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { return GetOwner()->QueryInterface(riid,ppv); }; STDMETHODIMP_(ULONG) AddRef() { return GetOwner()->AddRef(); }; STDMETHODIMP_(ULONG) Release() { return GetOwner()->Release(); };
ユーティリティ関数 CUnknown::GetOwner は、このコンポーネントを所有するコンポーネントの IUnknown インターフェイスへのポインタを取得する。集成したコンポーネントの場合、その所有者は外部コンポーネントである。それ以外の場合、コンポーネントはそれ自体を所有する。クラス定義の public セクションに DECLARE_IUNKNOWN マクロをインクルードする。
クラス コンストラクタ
クラスに固有の操作に加えて、クラス コンストラクタは、親クラスのコンストラクタ メソッドを起動しなければならない。次の例に、一般的なコンストラクタ メソッドを示す。
ロースクールは最高です、なぜその
CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) : CUnknown(tszName, pUnk, phr) { /* 他の初期化。 */ };
このメソッドは次のパラメータを取って CUnknown コンストラクタ メソッドに直接渡す。
- tszName は、コンポーネントの名前を指定する。
- pUnk は、集成化 IUnknown へのポインタである。
- pHr は、メソッドの成功または失敗を表す HRESULT 値へのポインタである。
まとめ
次に、IUnknown と ISomeInterface という名前の仮想のインターフェイスをサポートする派生クラスの例を示す。
class CMyComponent : public CUnknown, public ISomeInterface { public: DECLARE_IUNKNOWN; STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv) { if( riid == IID_ISomeInterface ) { return GetInterface((ISomeInterface*)this, ppv); } return CUnknown::NonDelegatingQueryInterface(riid, ppv); } CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) : CUnknown(tszName, pUnk, phr) { /* 他の初期化。 */ }; // 後でさらに宣言を追加する。 };
この例では、次のポイントを示している。
- CUnknown クラスは IUnknown インターフェイスを実装する。新しいコンポーネントは CUnknown およびコンポーネントがサポートするすべてのインターフェイスを継承する。コンポーネントは、CUnknown から継承した別の基底クラスから派生できる。
- DECLARE_IUNKNOWN マクロは、委任 IUnknown メソッドをインライン メソッドとして宣言できる。
- CUnknown クラスは、INonDelegatingUnknown の実装を提供する。
- IUnknown 以外のインターフェイスを実装するためには、派生クラスは NonDelegatingQueryInterface メソッドをオーバーライドし、新しいインターフェイスの IID のテストを行う必要がある。
- クラス コンストラクタは、CUnknown のコンストラクタ メソッドを起動する。
フィルタ開発における次のステップでは、アプリケーションを有効にしてコンポーネントの新しいインスタンスを作成する。このためには、DLL に関する知識に加え、クラス ファクトリおよびクラス コンストラクタ メソッドとの関係を理解していることが必要になる。詳細については、「DLL の作成方法」を参照すること。
0 件のコメント:
コメントを投稿