COM インターフェイスの使用

COM オブジェクトが作成されると、作成メソッドによってインターフェイス ポインターが返されます。その後、そのポインターを使用して、インターフェイスの任意のメソッドにアクセスできるようになります。構文は、C++ メソッドへのポインターを使用する場合と同じです。

追加のインターフェイスの要求

多くの場合、作成メソッドから受け取るインターフェイス ポインターは、必要とした 1 つのみとなります。実際に、オブジェクトが IUnknown 以外の 1 つのインターフェイスしかエクスポートしないことは、比較的よく見られます。しかし、多くのオブジェクトは複数のインターフェイスをエクスポートするため、それらの複数へのポインターが必要となる可能性があります。作成メソッドによって返された 1 つだけでなく、さらにインターフェイスが必要な場合、新しいオブジェクトを作成する必要はありません。代わりに、オブジェクトの IUnknown::QueryInterface メソッドを使用することによって、その他のインターフェイス ポインターを要求します。

CoCreateInstance でオブジェクトを作成する場合は、IUnknown インターフェイス ポインターを要求してから、IUnknown::QueryInterface を呼び出して必要なすべてのインターフェイスを要求できます。ただし、この手法は、1 つのインターフェイスしか必要ない場合には不便であり、返されるインターフェイス ポインターを指定できないオブジェクト作成メソッドを使用する場合は、まったく役に立ちません。実際には、すべての COM インターフェイスで IUnknown インターフェイスが拡張されるため、通常は明示的な IUnknown ポインターを取得する必要はありません。

インターフェイスの拡張は、C++ クラスからの継承と似ています。子インターフェイスによって、親インターフェイスのすべてのメソッドと、それ自体の 1 つ以上のメソッドが公開されます。実際に、"から継承" が "拡張" の代わりに使用される場合がよく見られます。覚えておく必要があるのは、継承は、オブジェクトの内部にあるということです。アプリケーションでは、オブジェクトのインターフェイスからの継承や、そのインターフェイスの拡張はできません。ただし、子インターフェイスを使用して、子または親の任意のメソッドを呼び出せます。

すべてのインターフェイスは IUnknown の子であるため、オブジェクトのために既に所有しているインターフェイス ポインターのいずれかを使用して、QueryInterface を呼び出せます。これを行うときは、要求しているインターフェイスの IID と、メソッドから返されるときにインターフェイス ポインターを含むポインターのアドレスを提供する必要があります。

たとえば、次のコードでは、IDirectSound9::CreateSoundBuffer を呼び出して、プライマリ バッファー オブジェクトを作成します。このオブジェクトは、複数のインターフェイスを公開します。CreateSoundBuffer メソッドによって、IDirectSoundBuffer9 インターフェイスが返されます。以降のコードでは、IDirectSoundBuffer9 インターフェイスを使用して、IDirectSound3DListener9 インターフェイスを要求するために QueryInterface を呼び出します。

IDirectSoundBuffer9* pDSBPrimary = NULL;
IDirectSound3DListener9* pDSListener;
...
if(FAILED(hr = g_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL )))
  return hr;

if(FAILED(hr = pDSBPrimary->QueryInterface(IID_IDirectSound3DListener9,
                                           (LPVOID *)&pDSListener)))
  return hr;