COM でのオブジェクトの作成

スレッドが COM ライブラリを初期化した後は、スレッドが COM インターフェイスを使用しても安全です。 COM インターフェイスを使用するには、まず、そのインターフェイスを実装する オブジェクトのインスタンスを作成します。

一般に、COM オブジェクトを作成するには 2 つの方法があります。

  • オブジェクトを実装するモジュールは、そのオブジェクトのインスタンスを作成するように特別に設計された関数を提供する場合があります。
  • または、COM は CoCreateInstance という名前のジェネリック作成関数を提供します。

たとえば、トピック「COM インターフェイスとは」の仮説Shapeオブジェクトを取得します。 この例では、 オブジェクトは Shape という名前 IDrawableのインターフェイスを実装します。 オブジェクトを実装するグラフィックス ライブラリは、次の Shape シグネチャを持つ関数をエクスポートする場合があります。

// Not an actual Windows function. 

HRESULT CreateShape(IDrawable** ppShape);

この関数を使用すると、次のように新 Shape しいオブジェクトを作成できます。

IDrawable *pShape;

HRESULT hr = CreateShape(&pShape);
if (SUCCEEDED(hr))
{
    // Use the Shape object.
}
else
{
    // An error occurred.
}

ppShape パラメーターの型は、ポインターからポインターへのポインターですIDrawable。 このパターンを見たことがない場合は、二重間接参照が不可解である可能性があります。

関数の要件を CreateShape 検討してください。 関数は、呼び出し元へのポインターを IDrawable 返す必要があります。 ただし、関数の戻り値は、エラー/成功コードに既に使用されています。 したがって、ポインターは 関数への引数を介して返される必要があります。 呼び出し元は型 IDrawable* の変数を関数に渡し、関数はこの変数を新 IDrawable しいポインターで上書きします。 C++ では、関数がパラメーター値を上書きする方法は、参照渡しまたはアドレス渡しの 2 つの方法のみです。 COM では、後者のパス バイ アドレスが使用されます。 また、ポインターのアドレスはポインターからポインターへのポインターであるため、パラメーターの型は である IDrawable**必要があります。

何が起こっているのかを視覚化するのに役立つ図を次に示します。

二重ポインターの間接参照を示す図

関数は CreateShapepShape (&pShape) のアドレスを使用して、 pShape に新しいポインター値を書き込みます。

CoCreateInstance: オブジェクトを作成する一般的な方法

CoCreateInstance 関数は、オブジェクトを作成するための汎用的なメカニズムを提供します。 CoCreateInstance を理解するには、2 つの COM オブジェクトが同じインターフェイスを実装でき、1 つのオブジェクトが 2 つ以上のインターフェイスを実装できることに注意してください。 したがって、オブジェクトを作成するジェネリック関数には、2 つの情報が必要です。

  • 作成するオブジェクト。
  • オブジェクトから取得するインターフェイス。

しかし、関数を呼び出すときに、この情報をどのように示しますか? COM では、オブジェクトまたはインターフェイスは、 グローバル一意識別子 (GUID) と呼ばれる 128 ビット番号を割り当てることによって識別されます。 GUID は、効果的に一意の方法で生成されます。 GUID は、中央登録機関なしで一意の識別子を作成する方法の問題を解決するソリューションです。 GUID は、 汎用一意識別子 (UUID) と呼ばれることもあります。 COM より前は、DCE/RPC (分散コンピューティング環境/リモート プロシージャ コール) で使用されていました。 新しい GUID を作成するためのアルゴリズムがいくつか存在します。 これらのアルゴリズムのすべてが一意性を厳密に保証するわけではありませんが、誤って同じ GUID 値を 2 回作成する可能性は非常に小さく、実質的にはゼロです。 GUID は、オブジェクトやインターフェイスだけでなく、あらゆる種類のエンティティを識別するために使用できます。 ただし、このモジュールではこれが唯一の使用です。

たとえば、ライブラリでは、次の Shapes 2 つの GUID 定数を宣言できます。

extern const GUID CLSID_Shape;
extern const GUID IID_IDrawable; 

(これらの定数の実際の 128 ビット数値は、他の場所で定義されていると仮定できます)。定数 CLSID_Shape はオブジェクトを Shape 識別し、定数 IID_IDrawable はインターフェイスを IDrawable 識別します。 プレフィックス "CLSID" は クラス識別子を表し、プレフィックス IIDインターフェイス識別子を表します。 これらは COM の標準的な名前付け規則です。

これらの値を指定すると、次のように新 Shape しいインスタンスを作成します。

IDrawable *pShape;
hr = CoCreateInstance(CLSID_Shape, NULL, CLSCTX_INPROC_SERVER, IID_IDrawable,
     reinterpret_cast<void**>(&pShape));

if (SUCCEEDED(hr))
{
    // Use the Shape object.
}
else
{
    // An error occurred.
}

CoCreateInstance 関数には、5 つのパラメーターがあります。 最初と 4 番目のパラメーターは、クラス識別子とインターフェイス識別子です。 実際、これらのパラメーターは関数に "Shape オブジェクトを作成し、IDrawable インターフェイスへのポインターを指定してください" と指示します。

2 番目のパラメーターを NULL に設定します。 (このパラメーターの意味の詳細については、COM ドキュメントの集計に関するトピックを参照してください)。3 番目のパラメーターは、オブジェクトの実行コンテキストを指定メイン目的を持つフラグのセットを受け取ります。 実行コンテキストは、オブジェクトがアプリケーションと同じプロセスで実行されるかどうかを指定します。同じコンピューター上の別のプロセスで。またはリモート コンピューター上。 次の表に、このパラメーターの最も一般的な値を示します。

フラグ 説明
CLSCTX_INPROC_SERVER 同じプロセス。
CLSCTX_LOCAL_SERVER 異なるプロセス、同じコンピューター。
CLSCTX_REMOTE_SERVER 別のコンピューター。
CLSCTX_ALL オブジェクトがサポートする最も効率的なオプションを使用します。 (最も効率的なものから最も効率的でないランク付けは、インプロセス、アウトプロセス、クロスコンピューターです)。

 

特定のコンポーネントのドキュメントでは、オブジェクトがサポートする実行コンテキストが示されている場合があります。 そうでない場合は、 CLSCTX_ALLを使用します。 オブジェクトがサポートしていない実行コンテキストを要求すると、 CoCreateInstance 関数はエラー コード REGDB_E_CLASSNOTREGを返します。 このエラー コードは、CLSID がユーザーのコンピューターに登録されているコンポーネントに対応していないことを示すこともできます。

CoCreateInstance の 5 番目のパラメーターは、 インターフェイスへのポインターを受け取ります。 CoCreateInstance はジェネリック メカニズムであるため、このパラメーターを厳密に型指定することはできません。 代わりに、データ型は void** であり、呼び出し元は void ** 型へのポインターのアドレスを強制する必要があります。 これは、前の例の reinterpret_cast の目的です。

CoCreateInstance の戻り値をチェックすることが重要です。 関数からエラー コードが返された場合、COM インターフェイス ポインターは無効であり、逆参照しようとするとプログラムがクラッシュする可能性があります。

内部的には、 CoCreateInstance 関数はさまざまな手法を使用してオブジェクトを作成します。 最も単純なケースでは、レジストリ内のクラス識別子を検索します。 レジストリ エントリは、 オブジェクトを実装する DLL または EXE を指します。 CoCreateInstance では、COM+ カタログまたはサイド バイ サイド (SxS) マニフェストからの情報を使用することもできます。 関係なく、詳細は呼び出し元に対して透過的です。 CoCreateInstance の内部の詳細については、「COM クライアントとサーバー」を参照してください。

使用している例は Shapes やや工夫されているため、実際の COM の動作例に目を向けてみましょう。ユーザーがファイルを選択するための [ 開く ] ダイアログ ボックスを表示します。

次へ

例: [開く] ダイアログ ボックス