Hi all,
I would like to discuss some code I'm using to manage COM objects with
intrusive_ptr.
1. I need to access the address of the raw pointer (to use QueryInterface).
Therefore I
implemented operator& for intrusive_ptr. Like in COM this pointer-pointer
will only
be used for intialization purposes. My implementation relies on the
intrusive_ptr's
memory layout and returns reinterpret_cast
Philipp Henkel wrote:
CComPtr-like usage: boost::intrusive_ptr<IVideo> video; someObject->QueryInterface(IID_IVideo,(void**)&video);
Is there a better way? How do you bring intrusive_ptr and QueryInterface together?
The technically correct way to use QueryInterface is to pass it the address
of a void*:
void* pv = 0;
someObject->QueryInterface( IID_IVideo, &pv );
IVideo * pv2 = static_cast< IVideo* >( pv );
boost::intrusive_ptr<IVideo> video( pv2 );
pv2->Release();
The (void**) cast is too error-prone, even if you don't care about
technicalities.
This of course can be encapsulated in a function.
template
CComPtr-like usage: boost::intrusive_ptr<IVideo> video; someObject->QueryInterface(IID_IVideo,(void**)&video);
Is there a better way? How do you bring intrusive_ptr and QueryInterface together?
The technically correct way to use QueryInterface is to pass it the address of a void*:
void* pv = 0; someObject->QueryInterface( IID_IVideo, &pv ); IVideo * pv2 = static_cast< IVideo* >( pv ); boost::intrusive_ptr<IVideo> video( pv2 ); pv2->Release();
Thanks for highlighting the ideal QueryInterface usage. The (void**) cast is too error-prone, even if you don't care about
technicalities.
Microsoft's CComPtr pushed me in that direction. Their CComPtr provides an operator&, too. This of course can be encapsulated in a function.
The encapsulation seems to be perfect in most cases. Unfortunately I've to
cope with some legacy (template) code for CComPtrs which relies on operator&. :-/ That's why I tried to provide it for intrusive_ptr. Is there a problem beside the void cast with my operator or its implementation? Of course, I can change the operator's signature to avoid the cast: template<typename T> void** operator&(intrusive_ptr<T>& ptr) By doing this nobody uses the operator by accident (or without thinking about it). Please note that I intend to use the operator with my legacy code only. In all other cases I'll prefer your query interface template. Thanks, Philipp
Philipp Henkel wrote:
The encapsulation seems to be perfect in most cases. Unfortunately I've to cope with some legacy (template) code for CComPtrs which relies on operator&. :-/ That's why I tried to provide it for intrusive_ptr. Is there a problem beside the void cast with my operator or its implementation?
The problem with operator& for a smart pointer is that the smart pointer can already have a value. When you hand the address of its raw pointer to QueryInterface, it will overwrite its old value without calling Release() on it. You can guard against that by always zeroing the pointer in operator&, but this leads to a different problem; the expression &x will set x to zero, something that isn't expected or intuitive. Operator& is evil. :-)
On 1/4/07, Peter Dimov
The problem with operator& for a smart pointer is that the smart pointer can already have a value. When you hand the address of its raw pointer to QueryInterface, it will overwrite its old value without calling Release() on it. You can guard against that by always zeroing the pointer in operator&, but this leads to a different problem; the expression &x will set x to zero, something that isn't expected or intuitive. Operator& is evil. :-)
One of (or both?) of Microsoft's smart pointers (i.e. IVideoPtr, CComPtr<IVideo>) assert if operator& is called and the pointer is not zero for that reason...or maybe it throws a COM exception, I can't remember. (Not disagreeing with anything that's been said, simply offering information the OP might find useful if he wants to make his operator behave like MS's). --Michael Fawcett
Philipp Henkel wrote:
I would like to discuss some code I'm using to manage COM objects with intrusive_ptr.
Out of interest, what's your motivation for using intrusive_ptr over the smart pointer facilities (via #import of your COM DLL/EXE) provided by Visual Studio? I quite like the smart pointer stuff; it almost makes COM-related programming half tolerable. You'd lose the benefits of things like IntelliSense completion for COM types if you wrolled your own wrapper, I would think. Trent.
On 1/8/07, Trent Nelson
Philipp Henkel wrote:
I would like to discuss some code I'm using to manage COM objects with intrusive_ptr.
Out of interest, what's your motivation for using intrusive_ptr over the smart pointer facilities (via #import of your COM DLL/EXE) provided by Visual Studio? I quite like the smart pointer stuff; it almost makes COM-related programming half tolerable. You'd lose the benefits of things like IntelliSense completion for COM types if you wrolled your own wrapper, I would think.
Heh :) Since IntelliSense crashes with boost.bind, most people wouldnt lose very much :-P.
Trent.
-- Felipe Magno de Almeida
Hi, On 1/8/07, Trent Nelson wrote:
Philipp Henkel wrote:
I would like to discuss some code I'm using to manage COM objects with intrusive_ptr.
Out of interest, what's your motivation for using intrusive_ptr over the smart pointer facilities (via #import of your COM DLL/EXE) provided by Visual Studio?
Internally the CComPtr often casts its raw pointer to IUnknown. That's no problem as long as you are using the CComPtr with COM interface classes only. Unfortunately I need a smart pointer for my implementation classes, too. Casts to IUnknown are ambiguous if the class implements two or more COM interfaces (dreaded diamond inheritance hierarchy) and therefore I thought about using another smart pointer. Additionally I'm not big fan of COM and that's why I prefer a lightweight reference counting solution like intrusive_ptr to handle my COM stuff. You'd lose the benefits of
things like IntelliSense completion for COM types if you wrolled your own wrapper, I would think.
That's not a problem. I'm using another code completion tool for VS. :-) Best regards, Philipp
May be you should take a look at Loki Library http://loki-lib.sourceforge.net initiated by A. Alexandrescu (Author of "Modern C++ Design"). There is a policy based smart pointer implementation and a policy to handle COM pointers. I just came across it some few weeks ago. With Kind Regards, Ovanes Markarian On Wed, January 17, 2007 13:08, Philipp Henkel wrote:
Hi,
On 1/8/07, Trent Nelson wrote:
Philipp Henkel wrote:
I would like to discuss some code I'm using to manage COM objects with intrusive_ptr.
Out of interest, what's your motivation for using intrusive_ptr over the smart pointer facilities (via #import of your COM DLL/EXE) provided by Visual Studio?
Internally the CComPtr often casts its raw pointer to IUnknown. That's no problem as long as you are using the CComPtr with COM interface classes only. Unfortunately I need a smart pointer for my implementation classes, too. Casts to IUnknown are ambiguous if the class implements two or more COM interfaces (dreaded diamond inheritance hierarchy) and therefore I thought about using another smart pointer. Additionally I'm not big fan of COM and that's why I prefer a lightweight reference counting solution like intrusive_ptr to handle my COM stuff.
You'd lose the benefits of
things like IntelliSense completion for COM types if you wrolled your own wrapper, I would think.
That's not a problem. I'm using another code completion tool for VS. :-)
Best regards, Philipp _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (6)
-
Felipe Magno de Almeida
-
Michael Fawcett
-
Ovanes Markarian
-
Peter Dimov
-
Philipp Henkel
-
Trent Nelson