Win32 App Creating an Object in COM - yoshimune/LearningDirectX11 GitHub Wiki
This page refers to 【Creating an Object in COM】
スレッドがCOMライブラリを初期化した後は、スレッドがCOMインターフェイスを使用しても安全です。COMインターフェイスを使用するには、プログラムは最初にインターフェイスを実装するオブジェクトのインスタンスを作成します。
一般的には、COMオブジェクトを作成するには2つの方法があります。
- オブジェクトを実装するモジュールは、そのオブジェクトのインスタンスを作成するために特別に設計された関数を提供するかもしれません
- あるいは、COMはCoCreateInstanceという汎用の作成関数を提供します。
例えば、What is a COM Interfaceで扱った仮想のShapeオブジェクトを取得します。この例では、ShapeオブジェクトがIDrawableインターフェイスを実装しています。Shapeオブジェクトを実装したグラフィックスライブラリは以下のシグネチャとともに関数を出力することがあります。
HRESULT CreateShape(IDrawable** ppShape);この関数を提供してください。以下のような新しいShapeオブジェクトを作成できます。
iDrawable *pShare;
HRESULT hr = CreateShape(&pShare);
if(SUCCEEDED(hr))
{
// Use the Shape object;
}
else
{
// An error occurred.
}ppShareパラメータは"IDrawableのポインタのポインタ"型です。もしこのパターンを知らない場合は、困惑するかもしれません。
CreateShape関数の要件を考慮してください。この関数はIDrawableポインタを呼び出し元に差し戻ししなくてはなりません。しかし、この関数の戻り値は、既に正常/エラーコードに使用されています。したがって、ポインタは関数の引数を利用して返す必要があります。呼び出し元はIDrawable*型の変数を関数に渡します。そして、関数はこの変数に新しいIDrawableポインタを上書きします。C++では、関数が引数を上書きする方法が二種類のみあります。参照渡し、またはアドレス渡しです。COMは後者のアドレス渡しを利用しています。そして、ポインタのアドレスは"ポインタのポインタ"となります。よってパラメータの型はIDrawable**とならなくてはなりません。
CreateShape関数はpShape(&pShape)のアドレスを使用して新しいポインタ値をpShapeに書き込みます。
CoCreateInstance関数はオブジェクトを作成するための汎用の機構を提供します。CoCreateInstanceを理解するためには、2つのCOMオブジェクトが同じインターフェイスを実装できること、一つのオブジェクトが2つ以上のインターフェイスを実装できることを覚えておいてください。したがって、オブジェクトを作成する汎用関数は2つの情報を必要とします。
- どのオブジェクトを作成するのか
- どのインターフェイスをオブジェクトから取得するのか
しかし、どうやってこの情報を関数呼び出し時に示せばよいでしょうか?COMでは、オブジェクトまたはインターフェイスは、割り当てられている128ビットの番号(globally unique identifer(GUID))によって特定されます。GUIDは完全にユニークとなるように生成されます。GUIDはどうやって包括的な機構を使わずに、ユニークな識別子を作成するための解決法です。GUIDは時々universally unique identifer(UUID)から呼ばれます。これらはCOMに先立って、DCE/RPC(Distributed Computing Enviroment/Remove Procedure Call)を使用します。新しいGUIDを作成するいくつかのアルゴリズムが存在します。これら全てのアルゴリズムが厳密な一意性を保証するわけではありません。しかし、同じGUID値を2つ作ってしまう確率は非常に小さく、殆ど0です。GUIDは、オブジェクトとインターフェイスを識別するだけでなく、整列したエンティティを識別するのに利用できます。 しかし、それがこのモジュールに関係する唯一の使い方です。
例えば、Shapeライブラリは2つ宣言されることもあります。
extern const GUID CLSID_Shape;
extern const GUID IID_IDrawable;(実際にこれらの定数の128-ビット数値は他の場所で定義されていると仮定できます。)CLSID_Shaoe定数はShapeオブジェクトを特定します。IID_IDrawable定数はIDrawableインターフェイスを識別します。接頭辞の"CLSID"は_class identifer_からきています。また、_IID_は_interface identifer_から来ています。これらは命名はCOMの一般的な規約に従っています。
これらの値を与えると、新しいShapeインスタンスが作成されます。
IDrawable *pShape;
hr = CoCreateInstance(CLSID_Shape, NULL, CLSCTX_INPROC_SERVER, IID_Drawable, reinterpret_cast<void**>(&pShape));
if(SUCCEEDED(hr))
{
// Use the Shape object.
}
else
{
// An error occured.
}内部的にCoCreateInstance関数はオブジェクト作成のために様々なテクニックを使っています。単純なケースでは、レジストリ内のクラス識別子をルックアップします。レジストリエントリーはオブジェクトを実装したDLLかEXEを指します。
CoCreateInstanceはまたCOM+ カタログかside-by-side(SxS)マニフェストからの情報を使用することができます。それにかかわらず、詳細は呼び出し側にとっては透過的です。詳細はCOM Clients and Serversを参照してください。