com::ptr (Clase)
Contenedor para un objeto COM que se puede usar como miembro de una clase de CLR. El contenedor también automatiza la administración de la duración del objeto COM, liberando todas las referencias en propiedad en el objeto cuando se llama a su destructor. Análogo a la clase CComPtr.
Sintaxis
template<class _interface_type>
ref class ptr;
Parámetros
_interface_type
Interfaz COM.
Comentarios
También se puede usar com::ptr
como variable de función local para simplificar varias tareas COM y automatizar la administración de la duración.
No se puede usar directamente com::ptr
como parámetro de función; use un operador de referencia de seguimiento o un identificador a un operador de objeto (^) en su lugar.
No se puede devolver directamente com::ptr
desde una función; use un identificador en su lugar.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La llamada a los métodos públicos de la clase da como resultado llamadas al objeto IXMLDOMDocument
contenido. El ejemplo crea una instancia de un documento XML, lo rellena con un XML simple y realiza un recorrido simplificado de los nodos del árbol de documentos analizados para imprimir el XML en la consola.
// 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>
Miembros
Constructores públicos
Nombre | Descripción |
---|---|
ptr::ptr | Construye un objeto com::ptr para encapsular un objeto COM. |
ptr::~ptr | Destruye un objeto com::ptr . |
Métodos públicos
Nombre | Descripción |
---|---|
ptr::Attach | Asocia un objeto COM a com::ptr . |
ptr::CreateInstance | Crea una instancia de un objeto COM dentro de com::ptr . |
ptr::Detach | Concede la propiedad del objeto COM y devuelve un puntero al objeto. |
ptr::GetInterface | Crea una instancia de un objeto COM dentro de com::ptr . |
ptr::QueryInterface | Consulta el objeto COM en propiedad de una interfaz y adjunta el resultado a otro com::ptr . |
ptr::Release | Libera todas las referencias en propiedad en el objeto COM. |
Operadores públicos
Nombre | Descripción |
---|---|
ptr::operator-> |
Operador de acceso a miembros, utilizado para llamar a métodos en el objeto COM en propiedad. |
ptr::operator= | Asocia un objeto COM a com::ptr . |
ptr::operator bool | Operador para usar com::ptr en una expresión condicional. |
ptr::operator! | Operador para determinar si el objeto COM en propiedad no es válido. |
Requisitos
Archivo de encabezado<msclr\com\ptr.h>
Espacio de nombres msclr::com
ptr::ptr
Devuelve un puntero al objeto COM en propiedad.
ptr();
ptr(
_interface_type * p
);
Parámetros
P
Puntero a interfaz COM.
Comentarios
El constructor sin argumentos asigna nullptr
al identificador de objeto subyacente. Las llamadas futuras a com::ptr
validarán el objeto interno y producirán un error silencioso hasta que se cree o adjunte un objeto.
El constructor de un argumento agrega una referencia al objeto COM, pero no libera la referencia del autor de la llamada, por lo que el autor de la llamada debe llamar a Release
en el objeto COM para renunciar realmente al control. Cuando se llama al destructor de com::ptr
, libera automáticamente sus referencias en el objeto COM.
El hecho de pasar NULL
a este constructor es lo mismo que llamar a la versión sin argumento.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. Muestra el uso de ambas versiones del constructor.
// 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
Destruye un objeto com::ptr
.
~ptr();
Comentarios
En la destrucción, com::ptr
libera todas las referencias que posee a su objeto COM. Asumiendo que no hay otras referencias al objeto COM, el objeto COM se eliminará y se liberará su memoria.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. En la función main
, se llamará a los destructores de los dos objetos XmlDocument
cuando salgan del ámbito del bloque try
, lo que da lugar a la llamada al destructor com::ptr
subyacente, liberando todas las referencias en propiedad al objeto 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
Asocia un objeto COM a com::ptr
.
void Attach(
_interface_type * _right
);
Parámetros
_right
Puntero de interfaz COM que se va a adjuntar.
Excepciones
Si com::ptr
ya posee una referencia a un objeto COM, Attach
inicia InvalidOperationException.
Comentarios
Una llamada a Attach
hace referencia al objeto COM, pero no libera la referencia del autor de la llamada a él.
El hecho de pasar NULL
a Attach
da como resultado que no se realice ninguna acción.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La función miembro ReplaceDocument
llama primero a Release
en cualquier objeto en propiedad anterior y, a continuación, llama a Attach
para adjuntar un nuevo objeto de documento.
// 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
Crea una instancia de un objeto COM dentro de com::ptr
.
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
);
Parámetros
progid
Cadena de ProgID
.
pouter
Puntero a la interfaz IUnknown del objeto agregado (el IUnknown de control). Si no se especifica pouter
, se usa NULL
.
cls_context
Contexto en el que se ejecutará el código que administra el objeto recién creado. Los valores se toman de la enumeración CLSCTX
. Si no se especifica cls_context
, se usa el valor CLSCTX_ALL.
rclsid
CLSID
asociado a los datos y al código que se usará para crear el objeto.
Excepciones
Si com::ptr
ya posee una referencia a un objeto COM, CreateInstance
inicia InvalidOperationException.
Esta función llama a CoCreateInstance
y usa ThrowExceptionForHR para convertir cualquier error HRESULT
en una excepción adecuada.
Comentarios
CreateInstance
usa CoCreateInstance
para crear una nueva instancia del objeto especificado, identificado a partir de un objeto ProgID o CLSID. com::ptr
hace referencia al objeto recién creado y liberará automáticamente todas las referencias en propiedad tras la destrucción.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. Los constructores de clase usan dos formas diferentes de CreateInstance
para crear el objeto de documento desde un objeto ProgID o desde un objeto CLSID más un 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
Concede la propiedad del objeto COM y devuelve un puntero al objeto.
_interface_type * Detach();
Valor devuelto
Puntero al objeto COM.
Si no hay ningún objeto en propiedad, se devuelve NULL.
Excepciones
Internamente, se llama a QueryInterface
en el objeto COM en propiedad y cualquier error HRESULT
se convierte en una excepción mediante ThrowExceptionForHR.
Comentarios
Detach
primero agrega una referencia al objeto COM en nombre del autor de la llamada y, a continuación, libera todas las referencias que pertenecen a com::ptr
. El autor de la llamada debe liberar en última instancia el objeto devuelto para destruirlo.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La función miembro DetachDocument
llama a Detach
para renunciar a la propiedad del objeto COM y devolver un puntero al autor de la llamada.
// 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
Devuelve un puntero al objeto COM en propiedad.
_interface_type * GetInterface();
Valor devuelto
Puntero al objeto COM en propiedad.
Excepciones
Internamente, se llama a QueryInterface
en el objeto COM en propiedad y cualquier error HRESULT
se convierte en una excepción mediante ThrowExceptionForHR.
Comentarios
com::ptr
agrega una referencia al objeto COM en nombre del autor de la llamada y también mantiene su propia referencia en el objeto COM. En última instancia, el autor de la llamada debe liberar la referencia en el objeto devuelto o nunca se destruirá.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La función miembro GetDocument
usa GetInterface
para devolver un puntero al objeto 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
Consulta el objeto COM en propiedad de una interfaz y adjunta el resultado a otro com::ptr
.
template<class _other_type>
void QueryInterface(
ptr<_other_type> % other
);
Parámetros
other
com::ptr
que obtendrá la interfaz.
Excepciones
Internamente, se llama a QueryInterface
en el objeto COM en propiedad y cualquier error HRESULT
se convierte en una excepción mediante ThrowExceptionForHR.
Comentarios
Utilice este método para crear un contenedor COM para una interfaz diferente del objeto COM propiedad del contenedor actual. Este método llama a QueryInterface
a través del objeto COM en propiedad para solicitar un puntero a una interfaz específica del objeto COM y adjunta el puntero de interfaz devuelto al com::ptr
pasado.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La función miembro WriteTopLevelNode
usa QueryInterface
para rellenar un elemento com::ptr
local con IXMLDOMNode
y, a continuación, pasa com::ptr
(mediante referencia de seguimiento) a una función miembro privada que escribe las propiedades de texto y nombre del nodo en la consola.
// 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
Libera todas las referencias en propiedad en el objeto COM.
void Release();
Comentarios
Al llamar a esta función, se liberan todas las referencias en propiedad en el objeto COM y se establece el identificador interno en nullptr
. Si no existen otras referencias en el objeto COM, se destruirá.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La función miembro ReplaceDocument
usa Release
para liberar cualquier objeto de documento anterior antes de adjuntar el nuevo documento.
// 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->
Operador de acceso a miembros, utilizado para llamar a métodos en el objeto COM en propiedad.
_detail::smart_com_ptr<_interface_type> operator->();
Valor devuelto
smart_com_ptr
al objeto COM.
Excepciones
Internamente, se llama a QueryInterface
en el objeto COM en propiedad y cualquier error HRESULT
se convierte en una excepción mediante ThrowExceptionForHR.
Comentarios
Este operador permite llamar a métodos del objeto COM en propiedad. Devuelve un valor temporal smart_com_ptr
que controla automáticamente sus propios AddRef
y Release
.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La función WriteDocument
usa operator->
para llamar al miembro get_firstChild
del objeto de documento.
// 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=
Asocia un objeto COM a com::ptr
.
ptr<_interface_type> % operator=(
_interface_type * _right
);
Parámetros
_right
Puntero de interfaz COM que se va a adjuntar.
Valor devuelto
Referencia de seguimiento en com::ptr
.
Excepciones
Si com::ptr
ya posee una referencia a un objeto COM, operator=
inicia InvalidOperationException.
Comentarios
La asignación de un objeto COM a com::ptr
hace referencia al objeto COM, pero no libera la referencia del autor de la llamada a él.
Este operador tiene el mismo efecto que Attach
.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La función miembro ReplaceDocument
llama primero a Release
en cualquier objeto en propiedad anterior y, a continuación, usa operator=
para adjuntar un nuevo objeto de documento.
// 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
Operador para usar com::ptr
en una expresión condicional.
operator bool();
Valor devuelto
true
si el objeto COM en propiedad es válido; false
de lo contrario.
Comentarios
El objeto COM en propiedad es válido si no es nullptr
.
Este operador se convierte en _detail_class::_safe_bool
, que es más seguro que bool
ya que no se puede convertir en un tipo entero.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La función miembro CreateInstance
usa operator bool
después de crear el nuevo objeto de documento para determinar si es válido y escribe en la consola si es así.
// 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!
Operador para determinar si el objeto COM en propiedad no es válido.
bool operator!();
Valor devuelto
true
si el objeto COM en propiedad no es válido; false
de lo contrario.
Comentarios
El objeto COM en propiedad es válido si no es nullptr
.
Ejemplo
En este ejemplo se implementa una clase CLR que usa com::ptr
para encapsular su objeto IXMLDOMDocument
miembro privado. La función miembro CreateInstance
usa operator!
para determinar si ya hay un objeto de documento en propiedad y solo crea una nueva instancia si el objeto no es válido.
// 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.