Windows COMプログラミング¶
Windows OSの基盤の一つがCOMです。
情報源¶
Webサイト¶
- [連載!とことんVC++]第1回 COM再入門~COMオブジェクトの基本的利用(COMクライアントの実装)~
- [連載!とことんVC++]第2回 COM再入門~COMオブジェクトの基本的実装~
- [連載!とことんVC++]第3回 Windows 7新機能におけるCOMの利用~C++によるジャンプリスト~
- [連載!とことんVC++]第4回 ATLによるCOMの利用(COMクライアント)
- [連載!とことんVC++]第5回 ATLによるCOMコンポーネントの基本構造の再確認
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);