--- description: "Learn more about: com::ptr Class" title: "com::ptr Class" ms.date: "01/16/2019" ms.topic: "reference" f1_keywords: ["msclr::com::ptr::ptr", "msclr::com::ptr::Attach", "msclr::com::ptr::CreateInstance", "msclr::com::ptr::Detach", "msclr::com::ptr::GetInterface", "msclr::com::ptr::QueryInterface", "msclr::com::ptr::Release", "msclr::com::ptr::operator=", "msclr::com::ptr::operator->", "msclr::com::ptr::operator!"] helpviewer_keywords: ["msclr::ptr class"] ms.assetid: 0144d0e4-919c-45f9-a3f8-fbc9edba32bf --- # com::ptr Class A wrapper for a COM object that can be used as a member of a CLR class. The wrapper also automates lifetime management of the COM object, releasing all owned references on the object when its destructor is called. Analogous to [CComPtr class](../atl/reference/ccomptr-class.md). ## Syntax ``` template ref class ptr; ``` ### Parameters *_interface_type*
COM interface. ## Remarks A `com::ptr` can also be used as a local function variable to simplify various COM tasks and to automate lifetime management. A `com::ptr` can't be used directly as a function parameter; use a [Tracking reference operator](../extensions/tracking-reference-operator-cpp-component-extensions.md) or a [Handle to object operator (^)](../extensions/handle-to-object-operator-hat-cpp-component-extensions.md) instead. A `com::ptr` can't be directly returned from a function; use a handle instead. ## Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. Calling the public methods of the class results in calls to the contained `IXMLDOMDocument` object. The sample creates an instance of an XML document, fills it with some simple XML, and does a simplified walk of the nodes in the parsed document tree to print the XML to the console. ```cpp // comptr.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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("", strName); } finally { ::SysFreeString(bstr); } } com::ptr 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("persnickety"); // write the document to the console doc.WriteXml(); } catch (Exception^ e) { Console::WriteLine(e); } } ``` ```Output persnickety ``` ## Members ### Public constructors |Name|Description| |---------|-----------| |[ptr::ptr](#ptr)|Constructs a `com::ptr` to wrap a COM object.| |[ptr::~ptr](#tilde-ptr)|Destructs a `com::ptr`.| ### Public methods |Name|Description| |---------|-----------| |[ptr::Attach](#attach)|Attaches a COM object to a `com::ptr`.| |[ptr::CreateInstance](#createInstance)|Creates an instance of a COM object within a `com::ptr`.| |[ptr::Detach](#detach)|Gives up ownership of the COM object, returning a pointer to the object.| |[ptr::GetInterface](#getInterface)|Creates an instance of a COM object within a `com::ptr`.| |[ptr::QueryInterface](#queryInterface)|Queries the owned COM object for an interface and attaches the result to another `com::ptr`.| |[ptr::Release](#release)|Releases all owned references on the COM object.| ### Public operators |Name|Description| |---------|-----------| |[`ptr::operator->`](#operator-arrow)|Member access operator, used to call methods on the owned COM object.| |[ptr::operator=](#operator-assign)|Attaches a COM object to a `com::ptr`.| |[ptr::operator bool](#operator-bool)|Operator for using `com::ptr` in a conditional expression.| |[ptr::operator!](#operator-logical-not)|Operator to determine if the owned COM object is invalid.| ## Requirements **Header file** \ **Namespace** msclr::com ## ptr::ptr Returns a pointer to the owned COM object. ```cpp ptr(); ptr( _interface_type * p ); ``` ### Parameters *P*
A COM interface pointer. ### Remarks The no-argument constructor assigns **`nullptr`** to the underlying object handle. Future calls to the `com::ptr` will validate the internal object and silently fail until an object is created or attached. The one-argument constructor adds a reference to the COM object but doesn't release the caller's reference, so the caller must call `Release` on the COM object to truly give up control. When the `com::ptr`'s destructor is called it will automatically release its references on the COM object. Passing `NULL` to this constructor is the same as calling the no-argument version. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. It demonstrates usage of both versions of the constructor. ```cpp // comptr_ptr.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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 Destructs a `com::ptr`. ```cpp ~ptr(); ``` ### Remarks On destruction, the `com::ptr` releases all references it owns to its COM object. Assuming that there are no other references held to the COM object, the COM object will be deleted and its memory freed. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. In the `main` function, the two `XmlDocument` objects' destructors will be called when they go out of the scope of the **`try`** block, resulting in the underlying `com::ptr` destructor being called, releasing all owned references to the COM object. ```cpp // comptr_dtor.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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 Attaches a COM object to a `com::ptr`. ```cpp void Attach( _interface_type * _right ); ``` ### Parameters *_right*
The COM interface pointer to attach. ### Exceptions If the `com::ptr` already owns a reference to a COM object, `Attach` throws . ### Remarks A call to `Attach` references the COM object but doesn't release the caller's reference to it. Passing `NULL` to `Attach` results in no action being taken. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The `ReplaceDocument` member function first calls `Release` on any previously owned object and then calls `Attach` to attach a new document object. ```cpp // comptr_attach.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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 Creates an instance of a COM object within a `com::ptr`. ```cpp 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 ); ``` ### Parameters *progid*
A `ProgID` string. *pouter*
Pointer to the aggregate object's IUnknown interface (the controlling IUnknown). If `pouter` isn't specified, `NULL` is used. *cls_context*
Context in which the code that manages the newly created object will run. The values are taken from the `CLSCTX` enumeration. If `cls_context` isn't specified, the value CLSCTX_ALL is used. *rclsid*
`CLSID` associated with the data and code that will be used to create the object. ### Exceptions If the `com::ptr` already owns a reference to a COM object, `CreateInstance` throws . This function calls `CoCreateInstance` and uses to convert any error `HRESULT` to an appropriate exception. ### Remarks `CreateInstance` uses `CoCreateInstance` to create a new instance of the specified object, identified either from a ProgID or a CLSID. The `com::ptr` references the newly created object and will automatically release all owned references upon destruction. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The class constructors use two different forms of `CreateInstance` to create the document object either from a ProgID or from a CLSID plus a CLSCTX. ```cpp // comptr_createinstance.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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 Gives up ownership of the COM object, returning a pointer to the object. ```cpp _interface_type * Detach(); ``` ### Return value The pointer to the COM object. If no object is owned, NULL is returned. ### Exceptions Internally, `QueryInterface` is called on the owned COM object and any error `HRESULT` is converted to an exception by . ### Remarks `Detach` first adds a reference to the COM object on behalf of the caller and then releases all references owned by the `com::ptr`. The caller must ultimately release the returned object to destroy it. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The `DetachDocument` member function calls `Detach` to give up ownership of the COM object and return a pointer to the caller. ```cpp // comptr_detach.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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"persnickety"); 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 Returns a pointer to the owned COM object. ```cpp _interface_type * GetInterface(); ``` ### Return value A pointer to the owned COM object. ### Exceptions Internally, `QueryInterface` is called on the owned COM object and any error `HRESULT` is converted to an exception by . ### Remarks The `com::ptr` adds a reference to the COM object on the caller's behalf and also keeps its own reference on the COM object. The caller must ultimately release the reference on the returned object or it will never be destroyed. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The `GetDocument` member function uses `GetInterface` to return a pointer to the COM object. ```cpp // comptr_getinterface.cpp // compile with: /clr /link msxml2.lib #include #include #import 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("", 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 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"persnickety"); 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(); } } } ``` ```Output persnickety ``` ## ptr::QueryInterface Queries the owned COM object for an interface and attaches the result to another `com::ptr`. ```cpp template void QueryInterface( ptr<_other_type> % other ); ``` ### Parameters *other*
The `com::ptr` that will get the interface. ### Exceptions Internally, `QueryInterface` is called on the owned COM object and any error `HRESULT` is converted to an exception by . ### Remarks Use this method to create a COM wrapper for a different interface of the COM object owned by the current wrapper. This method calls `QueryInterface` through the owned COM object to request a pointer to a specific interface of the COM object and attaches the returned interface pointer to the passed-in `com::ptr`. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The `WriteTopLevelNode` member function uses `QueryInterface` to fill a local `com::ptr` with an `IXMLDOMNode` and then passes the `com::ptr` (by tracking reference) to a private member function that writes the node's name and text properties to the console. ```cpp // comptr_queryinterface.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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 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 % 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("", strName); } finally { ::SysFreeString(bstr); } } com::ptr 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("persnickety"); // write the document to the console doc.WriteTopLevelNode(); } catch (Exception^ e) { Console::WriteLine(e); } } ``` ```Output <#document>persnickety ``` ## ptr::Release Releases all owned references on the COM object. ```cpp void Release(); ``` ### Remarks Calling this function releases all owned references on the COM object and sets the internal handle to the COM object to **`nullptr`**. If no other references on the COM object exist, it will be destroyed. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The `ReplaceDocument` member function uses `Release` to release any prior document object before attaching the new document. ```cpp // comptr_release.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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->` Member access operator, used to call methods on the owned COM object. ```cpp _detail::smart_com_ptr<_interface_type> operator->(); ``` ### Return value A `smart_com_ptr` to the COM object. ### Exceptions Internally, `QueryInterface` is called on the owned COM object and any error `HRESULT` is converted to an exception by . ### Remarks This operator allows you to call methods of the owned COM object. It returns a temporary `smart_com_ptr` that automatically handles its own `AddRef` and `Release`. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The `WriteDocument` function uses `operator->` to call the `get_firstChild` member of the document object. ```cpp // comptr_op_member.cpp // compile with: /clr /link msxml2.lib #include #include #import 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("", 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 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"persnickety"); 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(); } } } ``` ```Output persnickety ``` ## ptr::operator= Attaches a COM object to a `com::ptr`. ```cpp ptr<_interface_type> % operator=( _interface_type * _right ); ``` ### Parameters *_right*
The COM interface pointer to attach. ### Return value A tracking reference on the `com::ptr`. ### Exceptions If the `com::ptr` already owns a reference to a COM object, `operator=` throws . ### Remarks Assigning a COM object to a `com::ptr` references the COM object but doesn't release the caller's reference to it. This operator has the same effect as `Attach`. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The `ReplaceDocument` member function first calls `Release` on any previously owned object and then uses `operator=` to attach a new document object. ```cpp // comptr_op_assign.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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 Operator for using `com::ptr` in a conditional expression. ```cpp operator bool(); ``` ### Return value **`true`** if the owned COM object is valid; **`false`** otherwise. ### Remarks The owned COM object is valid if it's not **`nullptr`**. This operator converts to `_detail_class::_safe_bool` which is safer than **`bool`** because it can't be converted to an integral type. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The `CreateInstance` member function uses `operator bool` after creating the new document object to determine if it's valid and writes to the console if it is. ```cpp // comptr_op_bool.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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); } } ``` ```Output DOM Document created. ``` ## ptr::operator! Operator to determine if the owned COM object is invalid. ```cpp bool operator!(); ``` ### Return value **`true`** if the owned COM object is invalid; **`false`** otherwise. ### Remarks The owned COM object is valid if it's not **`nullptr`**. ### Example This example implements a CLR class that uses a `com::ptr` to wrap its private member `IXMLDOMDocument` object. The `CreateInstance` member function uses `operator!` to determine if a document object is already owned, and only creates a new instance if the object is invalid. ```cpp // comptr_op_not.cpp // compile with: /clr /link msxml2.lib #include #include #import 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 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); } } ``` ```Output DOM Document created. ```