プロジェクト

全般

プロフィール

Windows COMプログラミング

Windows OSの基盤の一つがCOMです。

情報源

Webサイト

COMの概念

言語非依存とインタフェース

ID、GUID、CLSIDおよびIID

COMでは、いろいろなものの識別のためにGUID(16バイト)を使います。

  • COMオブジェクトを識別する → CLSID(クラスID)
  • COMインタフェースを識別する → IID(インタフェースID)

プログラミングメモ

COMライブラリの初期化と終了

初期化

COMを使用するWindowsプログラムは、最初にCOMライブラリの初期化を行います。初期化は、COMを呼び出すスレッド個々に必要です。
COMは、アパートメントスレッドおよびマルチスレッドの2つのスレッドモデルがあります。ウィンドウを作成するスレッドの場合はアパートメントスレッドを、その他のスレッドはマルチスレッドを使用するのが一般的だそうです。(GUIのAPIはシングルスレッドルールなので)

アパートメントスレッドでの初期化例

HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr)) {
  // 成功
} else {
  // エラー
}
  • ほぼ廃止のOLE 1.0のオーバーヘッドを回避するため、COINIT_DISABLE_OLE1DDEを指定

終了

CoUninitialize();

エラーコード

成功/失敗の通知

COMのメソッド/関数は、HRESULT型(32bit整数)の値を返し、成功/失敗を通知します。最上位ビットが0は成功、1は失敗を示します。
成功/失敗を判別するマクロSUCCEEDED、FAILEDが用意されています。

ポインタ

ATLスマートポインタ

<atlbase.h>で提供されるCComPtrがあります。変数のスコープから外れると、スマートポインタのデストラクタで基のポインタに対してReleaseを呼び出します。

CComPtr<IFileOpenDialog> pFileOpen;
HRESULT hr = pFileOpen.CoCreateInstance(__uuidof(FileOpenDialog));
if (SUCCEEDED(hr)) {
  hr = pFileOpen->Show(NULL);
  if (SUCCEEDED(hr)) {
    CComPtr<IShellItem> pItem;
    hr = pFileOpen->GetResult(&pItem);
    if (SUCCEEDED(hr)) {
      // ...
    }
  } // pItemがスコープから外れる
} // pFileOpenがスコープから外れる

UUID(GUID)関連

GUIDを文字列化する

GUIDは、次の構造体です。

typedef struct _GUID {
    DWORD Data1;
    WORD  Data2;
    WORD  Data3;
    BYTE  Data4[8];
} GUID;

これを、可視化するため文字列にするWindows APIとして、StringFromGUID2とUuidToStringがあるそうです。

UuidToStringを使う場合は、次のシグネチャ(ワイド文字版)となります。Rpcrt4.libをリンクします。
RPC_STATUS RPC_ENTRY UuidToStringW(const UUID* uuid, RPC_WSTR* stringUuid);

#include <rpcdce.h>
  :
  RPC_WSTR waString;
  UuidToStringW(&id, &waString);
  std::wstring uuidText((wchar_t*) waString);
  RpcStringFree(&waString);