2004年10月31日

COMスマートポインタ

環境
Visual C++.NET 2003
ライブラリ
MSXML3

本記事では、WindowsのCOMライブラリを扱いやすくしてくれるcom_ptr_tクラスを紹介したいと思います。

com_ptr_tは、IUnknownインターフェースのQueryInterface、AddRef、Releaseメンバ関数周りを隠蔽してくれるテンプレートクラスで、いわゆるスマートポインタの一種です。

_com_ptr_tは、単体でもそれなりに便利ですが、これがVisual C++の色々な機能と結びついてさらに便利になっています。

例えばMSXML3を使ってXMLファイルを読み込むコードが、_com_ptr_tを使ってどのように簡単になるのかを見てみましょう。

#import "msxml3.dll" named_guids

int main(int argc, char* argv[])
{
  // COMライブラリ初期化
  ::CoInitialize(NULL);

  try {
    MSXML2::IXMLDOMDocument2Ptr pDoc;
    pDoc.CreateInstance(MSXML2::CLSID_DOMDocument);
    pDoc->async = false;
    if (pDoc->load(L"test.xml")) {
      // Root要素名を表示する
      printf("RootNodeName: %s\n",static_cast<const char*>(pDoc->documentElement->nodeName));
      // Root要素の子要素一覧
      MSXML2::IXMLDOMNodeListPtr pList = pDoc->documentElement->childNodes;
      for (long i = 0, n = pList->length; i < n; ++i) {
        MSXML2::IXMLDOMElementPtr pElement = pList->Getitem(i);
        if (pElement) {
          // 子ノードが要素の場合のみ処理する
          printf("ChildNodeName: %s\n",static_cast<const char*>(pElement->nodeName));
        }
      }
    }
  }catch (_com_error& e) {
    // 例外ハンドラ
    printf("Error: %s\n", e.ErrorMessage());
  }

  // COMライブラリ終了
  ::CoUninitialize();
  return 0;
}

面倒なQueryInterface、AddRef、Releaseが綺麗に消えていることが分かると思います。VBScriptに近いお手軽さです。

ところで、上記コードには、_com_ptr_tという文字列は存在しないということに注意して下さい。
_com_ptr_tが使われているのは、上記#importによって自動生成されるmsxml3.tlhというヘッダファイルの中です。ここに、

typedef _com_ptr_t<IXMLDOMDocument2, &__uuidof(IXMLDOMDocument2)> IXMLDOMDocument2Ptr;
typedef _com_ptr_t<IXMLDOMElement, &__uuidof(IXMLDOMElement)> IXMLDOMDocument2Ptr;

というような感じの定義があるのです。

何か不都合があると、_com_error例外を投げてくれるのもありがたいところです。例外処理がシンプルになります。

一度COM周りのコードを書いた人なら分かると思いますが、_com_ptr_tを使わずに上記のコードを書いてみると、相当大変です。_com_ptr_t万歳。

一応最後に書いておきますが、_com_ptr_tは、MSXML3に限らず、他のCOMインターフェースに対しても使えます。例えば、CreateStreamOnHGlobalで取得したIStreamをIStreamPtrに代入して・・・ということもできますし、DirectX9周りで活用することもできます。色々と試してみて下さい。
但し、_com_ptr_tは、Visual C++の独自機能を相当使っているはずです。移植性が必要な場合は、使わない方が良いでしょう。

投稿者 MASATO : 2004年10月31日 11:09 | トラックバック
コメント
コメントする









名前、アドレスを登録しますか?