18.04.2015 Views

ArcGIS Engine Developer Guide

ArcGIS Engine Developer Guide

ArcGIS Engine Developer Guide

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

C++ APPLICATION PROGRAMMING INTERFACE<br />

If you have used smart pointers before, you<br />

might have seen differences in the implementation<br />

of the equality (“==”) operator for smart<br />

pointer comparisons. The COM specification<br />

states object identity is performed by comparing<br />

the pointer values of IUnknown. The smart<br />

pointers will perform necessary QI and comparison<br />

when using the “==” operator.<br />

// results in an AddRef (if pointer is not 0).<br />

IBarPtr ipBar(m_ipBar);<br />

// Detach will clear the local smart pointer and the<br />

// interface is written into the output parameter.<br />

*pVal = ipBar.Detach();<br />

// This can be combined into one line:<br />

// *pVal = IBarPtr(m_ipBar).Detach();<br />

CComVariant(VARIANT_TRUE) will create a<br />

short integer variant (type VT_I2) and not a<br />

Boolean variant (type VT_BOOL) as expected.<br />

You can use CComVariant(true) to create a<br />

Boolean variant.<br />

return S_OK;<br />

}<br />

The above pattern has the same result as the following code. Note that a conditional<br />

test for a 0 pointer is required before AddRef can be called; calling<br />

AddRef (or any method) on a 0 pointer will result in an access violation exception<br />

and typically crash the application:<br />

HRESULT CFoo::get_Bar(IBar **pVal)<br />

{<br />

if (pVal==0) return E_POINTER;<br />

// Copy the interface pointer (no AddRef) into the output parameter.<br />

*pVal = m_ipBar;<br />

// Make sure the interface pointer is nonzero before calling AddRef.<br />

if (*pVal)<br />

*pVal->AddRef();<br />

CComVariant myVar(ipSmartPointer) will result<br />

in a variant type of Boolean (VT_BOOL) and<br />

not a variant with an object reference<br />

(VT_UNKNOWN) as expected. It is better to<br />

pass unambiguous types to constructors—that is,<br />

types that are not smart types with overloaded<br />

cast operators.<br />

// Perform QI of IUnknown.<br />

IUnknownPtr ipUnk = ipSmartPointer;<br />

// Ensure we use IUnknown* constructor of<br />

CComVariant.<br />

CComVariant myVar2(ipUnk.GetInterfacePtr());<br />

return S_OK;<br />

}<br />

When using a smart pointer to receive an object from an [out] parameter on a<br />

method, use the smart pointer “&” de-reference operator. This will cause the<br />

previous interface pointer in the smart pointer to be released. The smart pointer is<br />

then populated with the new [out] value. The implementation of the method will<br />

have already incremented the object reference count. This will be released when<br />

the smart pointer goes out of scope:<br />

{<br />

IFooPtr ipFoo1, ipFoo2;<br />

ipFoo1.CreateInstance(CLSID_Foo);<br />

ipFoo2.CreateInstance(CLSID_Foo);<br />

// Initialize ipBar Smart pointer from Foo1.<br />

IBarPtr ipBar;<br />

ipFoo1->get_Bar(&ipBar);<br />

// The "&" de-reference will call Release on ipBar.<br />

// ipBar is then repopulated with a new instance of IBar.<br />

ipFoo2->get_Bar(&ipBar);<br />

}<br />

// ipBar goes out of scope, and the smart pointer destructor calls Release.<br />

200 • <strong>ArcGIS</strong> <strong>Engine</strong> <strong>Developer</strong> <strong>Guide</strong>

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!