次の方法で共有


com::ptr Class

CLR クラスのメンバーとして使用できる COM オブジェクト用のラッパーです。 また、このラッパーは、COM オブジェクトの有効期間の管理を自動化します。デストラクターが呼び出されると、オブジェクトに対するすべての所有参照が解放されます。 CComPtr クラスに似ています。

構文

template<class _interface_type>
ref class ptr;

パラメーター

_interface_type
COM インターフェイス。

解説

com::ptr をローカル関数の変数として使用して、さまざまな COM タスクを簡略化したり、有効期間の管理を自動化したりすることもできます。

com::ptr を関数パラメーターとして直接使用することはできません。代わりに、参照演算子の追跡またはオブジェクト演算子 (^) へのハンドルを使用してください。

com::ptr は、関数から直接返すことはできません。代わりにハンドルを使用してください。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 クラスのパブリック メソッドを呼び出すと、含まれている IXMLDOMDocument オブジェクトが呼び出されます。 このサンプルでは、XML ドキュメントのインスタンスを作成し、そのインスタンスに単純な XML を格納します。また、解析されたドキュメント ツリー内のノードを簡略化して、XML をコンソールに出力します。

// comptr.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   void LoadXml(String^ xml) {
      pin_ptr<const wchar_t> pinnedXml = PtrToStringChars(xml);
      BSTR bstr = NULL;

      try {
         // load some XML into the document
         bstr = ::SysAllocString(pinnedXml);
         if (NULL == bstr) {
            throw gcnew OutOfMemoryException;
         }
         VARIANT_BOOL bIsSuccessful = false;
         // use operator -> to call IXMODOMDocument member function
         Marshal::ThrowExceptionForHR(m_ptrDoc->loadXML(bstr, &bIsSuccessful));
      }
      finally {
         ::SysFreeString(bstr);
      }
   }

   // simplified function to write just the first xml node to the console
   void WriteXml() {
      IXMLDOMNode* pNode = NULL;

      try {
         // the first child of the document is the first real xml node
         Marshal::ThrowExceptionForHR(m_ptrDoc->get_firstChild(&pNode));
         if (NULL != pNode) {
            WriteNode(pNode);
         }
      }
      finally {
         if (NULL != pNode) {
            pNode->Release();
         }
      }
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   // simplified function that only writes the node
   void WriteNode(IXMLDOMNode* pNode) {
      BSTR bstr = NULL;

      try {
         // write out the name and text properties
         Marshal::ThrowExceptionForHR(pNode->get_nodeName(&bstr));
         String^ strName = gcnew String(bstr);
         Console::Write("<{0}>", strName);
         ::SysFreeString(bstr);
         bstr = NULL;

         Marshal::ThrowExceptionForHR(pNode->get_text(&bstr));
         Console::Write(gcnew String(bstr));
         ::SysFreeString(bstr);
         bstr = NULL;

         Console::WriteLine("</{0}>", strName);
      }
      finally {
         ::SysFreeString(bstr);
      }
   }

   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// use the ref class to handle an XML DOM Document object
int main() {
   try {
      // create the class from a progid string
      XmlDocument doc("Msxml2.DOMDocument.3.0");

      // stream some xml into the document
      doc.LoadXml("<word>persnickety</word>");

      // write the document to the console
      doc.WriteXml();
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
}
<word>persnickety</word>

メンバー

パブリック コンストラクター

名前 説明
ptr::ptr COM オブジェクトをラップする com::ptr を構築します。
ptr::~ptr com::ptr を破棄します。

パブリック メソッド

名前 説明
ptr::Attach COM オブジェクトを com::ptr にアタッチします。
ptr::CreateInstance com::ptr 内に COM オブジェクトのインスタンスを作成します。
ptr::Detach COM オブジェクトの所有権を放棄し、オブジェクトへのポインターを返します。
ptr::GetInterface com::ptr 内に COM オブジェクトのインスタンスを作成します。
ptr::QueryInterface 所有する COM オブジェクトに対してインターフェイスを照会し、その結果を別の com::ptr にアタッチします。
ptr::Release COM オブジェクトに対するすべての所有参照を解放します。

パブリック演算子

名前 説明
ptr::operator-> メンバー アクセス演算子。所有する COM オブジェクトに対してメソッドを呼び出すために使用されます。
ptr::operator= COM オブジェクトを com::ptr にアタッチします。
ptr::operator bool 条件式で com::ptr を使用するための演算子。
ptr::operator! 所有する COM オブジェクトが無効かどうかを確認するための演算子。

必要条件

ヘッダー ファイル<msclr\com\ptr.h>

名前空間 msclr::com

ptr::ptr

所有する COM オブジェクトへのポインターを返します。

ptr();
ptr(
   _interface_type * p
);

パラメーター

P
COM インターフェイス ポインター。

解説

引数なしのコンストラクターは、基になるオブジェクト ハンドルに nullptr を割り当てます。 その後の com::ptr への呼び出しでは、内部オブジェクトが検証され、オブジェクトが作成またはアタッチされるまで、操作が警告なしに失敗します。

1 つの引数を持つコンストラクターは、COM オブジェクトへの参照を追加しますが、呼び出し元の参照は解放しません。そのため、呼び出し元は COM オブジェクトに対して Release を呼び出して、制御を完全に放棄する必要があります。 com::ptr のデストラクターが呼び出されると、COM オブジェクトに対する参照が自動的に解放されます。

このコンストラクターに NULL を渡すことは、引数なしのバージョンを呼び出すことと同じです。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 この例では、両方のバージョンのコンストラクターの使用方法を示しています。

// comptr_ptr.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   // construct the internal com::ptr with a COM object
   XmlDocument(IXMLDOMDocument* pDoc) : m_ptrDoc(pDoc) {}

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// use the ref class to handle an XML DOM Document object
int main() {
   IXMLDOMDocument* pDoc = NULL;

   try {
      // create an XML DOM document object
      Marshal::ThrowExceptionForHR(CoCreateInstance(CLSID_DOMDocument30, NULL,
         CLSCTX_ALL, IID_IXMLDOMDocument, (void**)&pDoc));
      // construct the ref class with the COM object
      XmlDocument doc1(pDoc);

      // or create the class from a progid string
      XmlDocument doc2("Msxml2.DOMDocument.3.0");
   }
   // doc1 and doc2 destructors are called when they go out of scope
   // and the internal com::ptr releases its reference to the COM object
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
   finally {
      if (NULL != pDoc) {
         pDoc->Release();
      }
   }
}

ptr::~ptr

com::ptr を破棄します。

~ptr();

解説

破棄が実行されると、com::ptr は、COM オブジェクトに対するすべての所有参照を解放します。 COM オブジェクトに対して保持されている他の参照がない場合は、COM オブジェクトが削除され、そのメモリが解放されます。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 main 関数では、2 つの XmlDocument オブジェクトが try ブロックのスコープから出たときに、それらのデストラクターが呼び出されます。その結果、基になる com::ptr デストラクターが呼び出され、COM オブジェクトへのすべての所有参照が解放されます。

// comptr_dtor.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   // construct the internal com::ptr with a COM object
   XmlDocument(IXMLDOMDocument* pDoc) : m_ptrDoc(pDoc) {}

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// use the ref class to handle an XML DOM Document object
int main() {
   IXMLDOMDocument* pDoc = NULL;

   try {
      // create an XML DOM document object
      Marshal::ThrowExceptionForHR(CoCreateInstance(CLSID_DOMDocument30, NULL,
         CLSCTX_ALL, IID_IXMLDOMDocument, (void**)&pDoc));
      // construct the ref class with the COM object
      XmlDocument doc1(pDoc);

      // or create the class from a progid string
      XmlDocument doc2("Msxml2.DOMDocument.3.0");
   }
   // doc1 and doc2 destructors are called when they go out of scope
   // and the internal com::ptr releases its reference to the COM object
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
   finally {
      if (NULL != pDoc) {
         pDoc->Release();
      }
   }
}

ptr::Attach

COM オブジェクトを com::ptr にアタッチします。

void Attach(
   _interface_type * _right
);

パラメーター

_right
アタッチする COM インターフェイス ポインター。

例外

com::ptr が COM オブジェクトへの参照を既に所有している場合、AttachInvalidOperationException をスローします。

解説

Attach への呼び出しでは COM オブジェクトが参照されますが、それに対する呼び出し元の参照は解放されません。

AttachNULL を渡した場合、アクションは実行されません。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 ReplaceDocument メンバー関数はまず、以前に所有していたオブジェクトに対して Release を呼び出し、次に Attach を呼び出して、新しいドキュメント オブジェクトをアタッチします。

// comptr_attach.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   // replace currently held COM object with another one
   void ReplaceDocument(IXMLDOMDocument* pDoc) {
      // release current document object
      m_ptrDoc.Release();
      // attach the new document object
      m_ptrDoc.Attach(pDoc);
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// unmanaged function that creates a raw XML DOM Document object
IXMLDOMDocument* CreateDocument() {
   IXMLDOMDocument* pDoc = NULL;
   Marshal::ThrowExceptionForHR(CoCreateInstance(CLSID_DOMDocument30, NULL,
      CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pDoc));
   return pDoc;
}

// use the ref class to handle an XML DOM Document object
int main() {
   IXMLDOMDocument* pDoc = NULL;

   try {
      // create the class from a progid string
      XmlDocument doc("Msxml2.DOMDocument.3.0");

      // get another document object from unmanaged function and
      // store it in place of the one held by our ref class
      pDoc = CreateDocument();
      doc.ReplaceDocument(pDoc);
      // no further need for raw object reference
      pDoc->Release();
      pDoc = NULL;
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
   finally {
      if (NULL != pDoc) {
         pDoc->Release();
      }
   }
}

ptr::CreateInstance

com::ptr 内に COM オブジェクトのインスタンスを作成します。

void CreateInstance(
   System::String ^ progid,
   LPUNKNOWN pouter,
   DWORD cls_context
);
void CreateInstance(
   System::String ^ progid,
   LPUNKNOWN pouter
);
void CreateInstance(
   System::String ^ progid
);
void CreateInstance(
   const wchar_t * progid,
   LPUNKNOWN pouter,
   DWORD cls_context
);
void CreateInstance(
   const wchar_t * progid,
   LPUNKNOWN pouter
);
void CreateInstance(
   const wchar_t * progid
);
void CreateInstance(
   REFCLSID rclsid,
   LPUNKNOWN pouter,
   DWORD cls_context
);
void CreateInstance(
   REFCLSID rclsid,
   LPUNKNOWN pouter
);
void CreateInstance(
   REFCLSID rclsid
);

パラメーター

progid
ProgID 文字列。

pouter
集約オブジェクトの IUnknown インターフェイス (controlling IUnknown) へのポインター。 pouter が指定されていない場合は、NULL が使用されます。

cls_context
新しく作成されたオブジェクトを管理するコードが実行されるコンテキスト。 値は CLSCTX 列挙値から取得されます。 cls_context が指定されていない場合は、値 CLSCTX_ALL が使用されます。

rclsid
オブジェクトの作成に使用されるデータとコードに関連付けられた CLSID

例外

com::ptr が COM オブジェクトへの参照を既に所有している場合、CreateInstanceInvalidOperationException をスローします。

この関数は CoCreateInstance を呼び出し、ThrowExceptionForHR を使用してエラー HRESULT を適切な例外に変換します。

解説

CreateInstanceCoCreateInstance を使用して、指定されたオブジェクトの新しいインスタンスを作成します (オブジェクトは、ProgID または CLSID から識別されます)。 com::ptr は、新しく作成された オブジェクトを参照し、破棄の際にはすべての所有参照を自動的に解放します。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 クラス コンストラクターは、2 つの異なる形式の CreateInstance を使用して、ProgID から、または CLSID と CLSCTX から、ドキュメント オブジェクトを作成します。

// comptr_createinstance.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }
   XmlDocument(REFCLSID clsid, DWORD clsctx) {
      m_ptrDoc.CreateInstance(clsid, NULL, clsctx);
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// use the ref class to handle an XML DOM Document object
int main() {
   try {
      // create the class from a progid string
      XmlDocument doc1("Msxml2.DOMDocument.3.0");

      // or from a clsid with specific CLSCTX
      XmlDocument doc2(CLSID_DOMDocument30, CLSCTX_INPROC_SERVER);
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
}

ptr::Detach

COM オブジェクトの所有権を放棄し、オブジェクトへのポインターを返します。

_interface_type * Detach();

戻り値

COM オブジェクトへのポインター。

所有されているオブジェクトがない場合は、NULL が返されます。

例外

内部的には、QueryInterface は所有する COM オブジェクトで呼び出され、エラー HRESULTThrowExceptionForHR によって例外に変換されます。

解説

Detach はまず、呼び出し元に代わって COM オブジェクトへの参照を追加し、com::ptr によって所有されているすべての参照を解放します。 呼び出し元は最終的に、返されたオブジェクトを解放して破棄する必要があります。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 DetachDocument メンバー関数は、Detach を呼び出して COM オブジェクトの所有権を放棄し、呼び出し元へのポインターを返します。

// comptr_detach.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   // detach the COM object and return it
   // this releases the internal reference to the object
   IXMLDOMDocument* DetachDocument() {
      return m_ptrDoc.Detach();
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// unmanaged function that loads XML into a raw XML DOM Document object
HRESULT LoadXml(IXMLDOMDocument* pDoc, BSTR bstrXml) {
   HRESULT hr = S_OK;
   VARIANT_BOOL bSuccess;
   hr = pDoc->loadXML(bstrXml, &bSuccess);
   if (S_OK == hr && !bSuccess) {
      hr = E_FAIL;
   }
   return hr;
}

// use the ref class to handle an XML DOM Document object
int main() {
   IXMLDOMDocument* pDoc = NULL;
   BSTR bstrXml = NULL;

   try {
      // create the class from a progid string
      XmlDocument doc("Msxml2.DOMDocument.3.0");

      bstrXml = ::SysAllocString(L"<word>persnickety</word>");
      if (NULL == bstrXml) {
         throw gcnew OutOfMemoryException("bstrXml");
      }
      // detach the document object from the ref class
      pDoc = doc.DetachDocument();
      // use unmanaged function and raw object to load xml
      Marshal::ThrowExceptionForHR(LoadXml(pDoc, bstrXml));
      // release document object as the ref class no longer owns it
      pDoc->Release();
      pDoc = NULL;
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
   finally {
      if (NULL != pDoc) {
         pDoc->Release();
      }

   }
}

ptr::GetInterface

所有する COM オブジェクトへのポインターを返します。

_interface_type * GetInterface();

戻り値

所有する COM オブジェクトへのポインター。

例外

内部的には、QueryInterface は所有する COM オブジェクトで呼び出され、エラー HRESULTThrowExceptionForHR によって例外に変換されます。

解説

com::ptr は、呼び出し元の代わりに COM オブジェクトへの参照を追加し、COM オブジェクトに対する独自の参照も保持します。 呼び出し元は、最終的に、返されたオブジェクトに対する参照を解放する必要があります。そうしないと、オブジェクトはいつまでも破棄されません。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 GetDocument メンバー関数は、GetInterface を使用して COM オブジェクトへのポインターを返します。

// comptr_getinterface.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   // add a reference to and return the COM object
   // but keep an internal reference to the object
   IXMLDOMDocument* GetDocument() {
      return m_ptrDoc.GetInterface();
   }

   // simplified function that only writes the first node
   void WriteDocument() {
      IXMLDOMNode* pNode = NULL;
      BSTR bstr = NULL;

      try {
         // use operator -> to call XML Doc member
         Marshal::ThrowExceptionForHR(m_ptrDoc->get_firstChild(&pNode));
         if (NULL != pNode) {
            // write out the xml
            Marshal::ThrowExceptionForHR(pNode->get_nodeName(&bstr));
            String^ strName = gcnew String(bstr);
            Console::Write("<{0}>", strName);
            ::SysFreeString(bstr);
            bstr = NULL;

            Marshal::ThrowExceptionForHR(pNode->get_text(&bstr));
            Console::Write(gcnew String(bstr));
            ::SysFreeString(bstr);
            bstr = NULL;

            Console::WriteLine("</{0}>", strName);
         }
      }
      finally {
         if (NULL != pNode) {
            pNode->Release();
         }
         ::SysFreeString(bstr);
      }
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// unmanaged function that loads XML into a raw XML DOM Document object
HRESULT LoadXml(IXMLDOMDocument* pDoc, BSTR bstrXml) {
   HRESULT hr = S_OK;
   VARIANT_BOOL bSuccess;
   hr = pDoc->loadXML(bstrXml, &bSuccess);
   if (S_OK == hr && !bSuccess) {
      hr = E_FAIL;
   }
   return hr;
}

// use the ref class to handle an XML DOM Document object
int main() {
   IXMLDOMDocument* pDoc = NULL;
   BSTR bstrXml = NULL;

   try {
      // create the class from a progid string
      XmlDocument doc("Msxml2.DOMDocument.3.0");

      bstrXml = ::SysAllocString(L"<word>persnickety</word>");
      if (NULL == bstrXml) {
         throw gcnew OutOfMemoryException("bstrXml");
      }
      // detach the document object from the ref class
      pDoc = doc.GetDocument();
      // use unmanaged function and raw object to load xml
      Marshal::ThrowExceptionForHR(LoadXml(pDoc, bstrXml));
      // release reference to document object (but ref class still references it)
      pDoc->Release();
      pDoc = NULL;

      // call another function on the ref class
      doc.WriteDocument();
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
   finally {
      if (NULL != pDoc) {
         pDoc->Release();
      }

   }
}
<word>persnickety</word>

ptr::QueryInterface

所有する COM オブジェクトに対してインターフェイスを照会し、その結果を別の com::ptr にアタッチします。

template<class _other_type>
void QueryInterface(
   ptr<_other_type> % other
);

パラメーター

other
インターフェイスを取得する com::ptr

例外

内部的には、QueryInterface は所有する COM オブジェクトで呼び出され、エラー HRESULTThrowExceptionForHR によって例外に変換されます。

解説

このメソッドは、現在のラッパーによって所有されている COM オブジェクトの別のインターフェイス用の COM ラッパーを作成するために使用されます。 このメソッドは、所有する COM オブジェクトを介して QueryInterface を呼び出し、COM オブジェクトの特定のインターフェイスへのポインターを要求して、返されたインターフェイス ポインターを、渡された com::ptr にアタッチします。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 WriteTopLevelNode メンバー関数は、QueryInterface を使用してローカルの com::ptrIXMLDOMNode を設定した後、ノードの名前とテキスト プロパティをコンソールに書き込むプライベート メンバー関数に、その com::ptr を (追跡参照によって) 渡します。

// comptr_queryinterface.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   void LoadXml(String^ xml) {
      pin_ptr<const wchar_t> pinnedXml = PtrToStringChars(xml);
      BSTR bstr = NULL;

      try {
         // load some XML into our document
         bstr = ::SysAllocString(pinnedXml);
         if (NULL == bstr) {
            throw gcnew OutOfMemoryException;
         }
         VARIANT_BOOL bIsSuccessful = false;
         // use operator -> to call IXMODOMDocument member function
         Marshal::ThrowExceptionForHR(m_ptrDoc->loadXML(bstr, &bIsSuccessful));
      }
      finally {
         ::SysFreeString(bstr);
      }
   }

   // write the top level node to the console
   void WriteTopLevelNode() {
      com::ptr<IXMLDOMNode> ptrNode;

      // query for the top level node interface
      m_ptrDoc.QueryInterface(ptrNode);
      WriteNode(ptrNode);
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   // simplified function that only writes the node
   void WriteNode(com::ptr<IXMLDOMNode> % node) {
      BSTR bstr = NULL;

      try {
         // write out the name and text properties
         Marshal::ThrowExceptionForHR(node->get_nodeName(&bstr));
         String^ strName = gcnew String(bstr);
         Console::Write("<{0}>", strName);
         ::SysFreeString(bstr);
         bstr = NULL;

         Marshal::ThrowExceptionForHR(node->get_text(&bstr));
         Console::Write(gcnew String(bstr));
         ::SysFreeString(bstr);
         bstr = NULL;

         Console::WriteLine("</{0}>", strName);
      }
      finally {
         ::SysFreeString(bstr);
      }
   }

   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// use the ref class to handle an XML DOM Document object
int main() {
   try {
      // create the class from a progid string
      XmlDocument doc("Msxml2.DOMDocument.3.0");

      // stream some xml into the document
      doc.LoadXml("<word>persnickety</word>");

      // write the document to the console
      doc.WriteTopLevelNode();
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
}
<#document>persnickety</#document>

ptr::Release

COM オブジェクトに対するすべての所有参照を解放します。

void Release();

解説

この関数を呼び出すと、COM オブジェクトに対するすべての所有参照が解放され、COM オブジェクトに対する内部ハンドルが nullptr に設定されます。 COM オブジェクトに対する他の参照が存在しない場合は、そのオブジェクトが破棄されます。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 ReplaceDocument メンバー関数は、新しいドキュメントをアタッチする前に、Release を使用して以前のドキュメント オブジェクトを解放します。

// comptr_release.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   // replace currently held COM object with another one
   void ReplaceDocument(IXMLDOMDocument* pDoc) {
      // release current document object
      m_ptrDoc.Release();
      // attach the new document object
      m_ptrDoc.Attach(pDoc);
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// unmanaged function that creates a raw XML DOM Document object
IXMLDOMDocument* CreateDocument() {
   IXMLDOMDocument* pDoc = NULL;
   Marshal::ThrowExceptionForHR(CoCreateInstance(CLSID_DOMDocument30, NULL,
      CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pDoc));
   return pDoc;
}

// use the ref class to handle an XML DOM Document object
int main() {
   IXMLDOMDocument* pDoc = NULL;

   try {
      // create the class from a progid string
      XmlDocument doc("Msxml2.DOMDocument.3.0");

      // get another document object from unmanaged function and
      // store it in place of the one held by our ref class
      pDoc = CreateDocument();
      doc.ReplaceDocument(pDoc);
      // no further need for raw object reference
      pDoc->Release();
      pDoc = NULL;
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
   finally {
      if (NULL != pDoc) {
         pDoc->Release();
      }
   }
}

ptr::operator->

メンバー アクセス演算子。所有する COM オブジェクトに対してメソッドを呼び出すために使用されます。

_detail::smart_com_ptr<_interface_type> operator->();

戻り値

COM オブジェクトへの smart_com_ptr

例外

内部的には、QueryInterface は所有する COM オブジェクトで呼び出され、エラー HRESULTThrowExceptionForHR によって例外に変換されます。

解説

この演算子を使用すると、所有する COM オブジェクトのメソッドを呼び出すことができます。 独自の AddRefRelease を自動的に処理する、一時的な smart_com_ptr を返します。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 WriteDocument 関数は、operator-> を使用してドキュメント オブジェクトの get_firstChild メンバーを呼び出します。

// comptr_op_member.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   // add a reference to and return the COM object
   // but keep an internal reference to the object
   IXMLDOMDocument* GetDocument() {
      return m_ptrDoc.GetInterface();
   }

   // simplified function that only writes the first node
   void WriteDocument() {
      IXMLDOMNode* pNode = NULL;
      BSTR bstr = NULL;

      try {
         // use operator -> to call XML Doc member
         Marshal::ThrowExceptionForHR(m_ptrDoc->get_firstChild(&pNode));
         if (NULL != pNode) {
            // write out the xml
            Marshal::ThrowExceptionForHR(pNode->get_nodeName(&bstr));
            String^ strName = gcnew String(bstr);
            Console::Write("<{0}>", strName);
            ::SysFreeString(bstr);
            bstr = NULL;

            Marshal::ThrowExceptionForHR(pNode->get_text(&bstr));
            Console::Write(gcnew String(bstr));
            ::SysFreeString(bstr);
            bstr = NULL;

            Console::WriteLine("</{0}>", strName);
         }
      }
      finally {
         if (NULL != pNode) {
            pNode->Release();
         }
         ::SysFreeString(bstr);
      }
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// unmanaged function that loads XML into a raw XML DOM Document object
HRESULT LoadXml(IXMLDOMDocument* pDoc, BSTR bstrXml) {
   HRESULT hr = S_OK;
   VARIANT_BOOL bSuccess;
   hr = pDoc->loadXML(bstrXml, &bSuccess);
   if (S_OK == hr && !bSuccess) {
      hr = E_FAIL;
   }
   return hr;
}

// use the ref class to handle an XML DOM Document object
int main() {
   IXMLDOMDocument* pDoc = NULL;
   BSTR bstrXml = NULL;

   try {
      // create the class from a progid string
      XmlDocument doc("Msxml2.DOMDocument.3.0");

      bstrXml = ::SysAllocString(L"<word>persnickety</word>");
      if (NULL == bstrXml) {
         throw gcnew OutOfMemoryException("bstrXml");
      }
      // detach the document object from the ref class
      pDoc = doc.GetDocument();
      // use unmanaged function and raw object to load xml
      Marshal::ThrowExceptionForHR(LoadXml(pDoc, bstrXml));
      // release reference to document object (but ref class still references it)
      pDoc->Release();
      pDoc = NULL;

      // call another function on the ref class
      doc.WriteDocument();
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
   finally {
      if (NULL != pDoc) {
         pDoc->Release();
      }

   }
}
<word>persnickety</word>

ptr::operator=

COM オブジェクトを com::ptr にアタッチします。

ptr<_interface_type> % operator=(
   _interface_type * _right
);

パラメーター

_right
アタッチする COM インターフェイス ポインター。

戻り値

com::ptr に対する追跡参照。

例外

com::ptr が COM オブジェクトへの参照を既に所有している場合、operator=InvalidOperationException をスローします。

解説

com::ptr に COM オブジェクトを割り当てると、その COM オブジェクトが参照されますが、それに対する呼び出し元の参照は解放されません。

この演算子は、Attach と同じ効果を持ちます。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 ReplaceDocument メンバー関数はまず、以前に所有していたオブジェクトに対して Release を呼び出し、次に operator= を使用して、新しいドキュメント オブジェクトをアタッチします。

// comptr_op_assign.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   // construct the internal com::ptr with a null interface
   // and use CreateInstance to fill it
   XmlDocument(String^ progid) {
      m_ptrDoc.CreateInstance(progid);
   }

   // replace currently held COM object with another one
   void ReplaceDocument(IXMLDOMDocument* pDoc) {
      // release current document object
      m_ptrDoc.Release();
      // attach the new document object
      m_ptrDoc = pDoc;
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// unmanaged function that creates a raw XML DOM Document object
IXMLDOMDocument* CreateDocument() {
   IXMLDOMDocument* pDoc = NULL;
   Marshal::ThrowExceptionForHR(CoCreateInstance(CLSID_DOMDocument30, NULL,
      CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pDoc));
   return pDoc;
}

// use the ref class to handle an XML DOM Document object
int main() {
   IXMLDOMDocument* pDoc = NULL;

   try {
      // create the class from a progid string
      XmlDocument doc("Msxml2.DOMDocument.3.0");

      // get another document object from unmanaged function and
      // store it in place of the one held by the ref class
      pDoc = CreateDocument();
      doc.ReplaceDocument(pDoc);
      // no further need for raw object reference
      pDoc->Release();
      pDoc = NULL;
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
   finally {
      if (NULL != pDoc) {
         pDoc->Release();
      }
   }
}

ptr::operator bool

条件式で com::ptr を使用するための演算子。

operator bool();

戻り値

所有する COM オブジェクトが有効な場合は true。それ以外の場合は false

解説

所有する COM オブジェクトは、nullptr でなければ有効です。

この演算子は、整数型に変換できないため、bool より安全な _detail_class::_safe_bool に変換されます。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 CreateInstance メンバー関数は、新しいドキュメント オブジェクトを作成した後、operator bool を使用してそれが有効かどうかを確認し、有効であればコンソールに書き込みます。

// comptr_op_bool.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   void CreateInstance(String^ progid) {
      if (!m_ptrDoc) {
         m_ptrDoc.CreateInstance(progid);
         if (m_ptrDoc) { // uses operator bool
            Console::WriteLine("DOM Document created.");
         }
      }
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// use the ref class to handle an XML DOM Document object
int main() {
   try {
      XmlDocument doc;
      // create the instance from a progid string
      doc.CreateInstance("Msxml2.DOMDocument.3.0");
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
}
DOM Document created.

ptr::operator!

所有する COM オブジェクトが無効かどうかを確認するための演算子。

bool operator!();

戻り値

所有する COM オブジェクトが無効な場合は true。それ以外の場合は false

解説

所有する COM オブジェクトは、nullptr でなければ有効です。

この例では、com::ptr を使用してプライベートメンバーの IXMLDOMDocument オブジェクトをラップする CLR クラスを実装しています。 CreateInstance メンバー関数は、operator! を使用してドキュメント オブジェクトが既に所有されているかどうかを確認し、オブジェクトが無効な場合にのみ、新しいインスタンスを作成します。

// comptr_op_not.cpp
// compile with: /clr /link msxml2.lib
#include <msxml2.h>
#include <msclr\com\ptr.h>

#import <msxml3.dll> raw_interfaces_only

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr;

// a ref class that uses a com::ptr to contain an
// IXMLDOMDocument object
ref class XmlDocument {
public:
   void CreateInstance(String^ progid) {
      if (!m_ptrDoc) {
         m_ptrDoc.CreateInstance(progid);
         if (m_ptrDoc) {
            Console::WriteLine("DOM Document created.");
         }
      }
   }

   // note that the destructor will call the com::ptr destructor
   // and automatically release the reference to the COM object

private:
   com::ptr<IXMLDOMDocument> m_ptrDoc;
};

// use the ref class to handle an XML DOM Document object
int main() {
   try {
      XmlDocument doc;
      // create the instance from a progid string
      doc.CreateInstance("Msxml2.DOMDocument.3.0");
   }
   catch (Exception^ e) {
      Console::WriteLine(e);
   }
}
DOM Document created.