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 オブジェクトへの参照を既に所有している場合、Attach
は InvalidOperationException をスローします。
解説
Attach
への呼び出しでは COM オブジェクトが参照されますが、それに対する呼び出し元の参照は解放されません。
Attach
に NULL
を渡した場合、アクションは実行されません。
例
この例では、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 オブジェクトへの参照を既に所有している場合、CreateInstance
は InvalidOperationException をスローします。
この関数は CoCreateInstance
を呼び出し、ThrowExceptionForHR を使用してエラー HRESULT
を適切な例外に変換します。
解説
CreateInstance
は CoCreateInstance
を使用して、指定されたオブジェクトの新しいインスタンスを作成します (オブジェクトは、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 オブジェクトで呼び出され、エラー HRESULT
は ThrowExceptionForHR によって例外に変換されます。
解説
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 オブジェクトで呼び出され、エラー HRESULT
は ThrowExceptionForHR によって例外に変換されます。
解説
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 オブジェクトで呼び出され、エラー HRESULT
は ThrowExceptionForHR によって例外に変換されます。
解説
このメソッドは、現在のラッパーによって所有されている COM オブジェクトの別のインターフェイス用の COM ラッパーを作成するために使用されます。 このメソッドは、所有する COM オブジェクトを介して QueryInterface
を呼び出し、COM オブジェクトの特定のインターフェイスへのポインターを要求して、返されたインターフェイス ポインターを、渡された com::ptr
にアタッチします。
例
この例では、com::ptr
を使用してプライベートメンバーの IXMLDOMDocument
オブジェクトをラップする CLR クラスを実装しています。 WriteTopLevelNode
メンバー関数は、QueryInterface
を使用してローカルの com::ptr
に IXMLDOMNode
を設定した後、ノードの名前とテキスト プロパティをコンソールに書き込むプライベート メンバー関数に、その 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 オブジェクトで呼び出され、エラー HRESULT
は ThrowExceptionForHR によって例外に変換されます。
解説
この演算子を使用すると、所有する COM オブジェクトのメソッドを呼び出すことができます。 独自の AddRef
と Release
を自動的に処理する、一時的な 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.