[C++ / Win32 / ATL] CComPtr assign ZONDER addRef()

Pagina: 1
Acties:

  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Hoi,

Ik heb een functie die een IUnkown* teruggeeft. Deze heeft al een mooi AddRef() gekregen.

Maar ik zou graag gebruik maken van de mooie cleane en zelf - releasende code van CComPtr.

Maar als ik

C++:
1
2
3
4
5
6
7
IUnkown* mijnFunction()
{
        //doe een queryInterface ofzo.. die dus AddRef
       return myAddReffedUnkown;
}

CComPtr< IUnknown > tPtr = mijnFunction();

doe dan denk ik dat door de assign er nogmaals een AddRef() wordt gedaan en dus zelfs als de tPtr out of scope gaat er slecht 1 keer Released() worden.

Is er een methode om toch de pointer door te geven (zonder naturllijk op de volgende regel meteen een Release() te doen?).

Nergens eigenlijk over dat gebruik gevonden omdat de meeste functions in /*out*/ gebruiken (ie - AdressOF, die wel 'VIES' maar prachtisch, wordt teruggeven als Raw Pointer).

Ik wil niet echt mijn eigen CComPtr gaan uitbreiden maar lijkt me toch weird dat dit er niet inzit...

Greetz

Onno

[ Voor 10% gewijzigd door hobbit_be op 24-05-2005 16:59 ]


  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Meestal wil je in je gehele programma smart pointers gebruiken, niet alleen in een klein stuk. En dan hoef je dat probleem niet tegen te komen, want dan kan je je smart pointers rechtstreeks laten vullen door QueryInterface:

C++:
1
2
CComPtr<IDispatch> spDispatch;
pUnknown->QueryInterface(IID_IDispatch, (void **)&spDispatch);


De reden waarom dit werkt is dat de address-of operator "&" van CComPtr is geoverload om het adres van de 'echte' interface-pointer terug te geven. QueryInterface zal dus de interface-pointer van spDispatch zonder hulp van CComPtr zetten. QI is dan ook de enige die de reference count ophoogt, en als spDispatch uit scope gaat, zal Release() ervoor zorgen dat de enige reference verdwijnt en het com-object wordt opgeruimd.

In alle andere gevallen zit er volgens mij niks anders op dan handmatig Release() aan te roepen. Persoonlijk vind ik dit niet fout, aangezien je dit zonder smart-pointers sowiezo hoort te doen als je klaar bent met een interface-pointer. Je moet het zien als de prijs die je betaalt door niet overal smart pointers te gebruiken.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Lijkt me inderdaad te kloppen, 1 handmatige AddRef = 1 handmatige Release. Je kunt natuurlijk ook een subtiele wrapper maken (niet getest):
C++:
1
2
3
4
5
6
7
8
class AssignAndThenRelease {
  IUnknown* tmp;
public:
  AssignAndThenRelease( IUnknown* tmp ) : tmp(tmp) { }
  operator IUnknown*() const { return tmp; }
  ~AssignAndThenRelease() { Release(tmp); }
};
CComPtr< IUnknown > tPtr = AssignAndThenRelease(mijnFunction());

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • hobbit_be
  • Registratie: November 2002
  • Laatst online: 04-07-2025
Hoi, beetje later maar on holliday.

Blijkbaar heeft de CComPtr ook een ->Attach(methode) die doet wat ik wil. Oh en ik begrijp dat het mixen niet echt proper is (maar het moet werken met bestaande code, die van Microsoft zelf)

dit was mijn oplossing dus
C++:
1
2
3
4
5
6
7
template<class T > 
   CComPtr<T> Raw2Smart(T* aRawButAddReffedPointer)
{
   CComPtr< T > tTemp = NULL; 
   tTemp.Attach(aRawButAddReffedPointer);
   return tTemp;
};


Niet een wrapper maar een autocreate CComPtr...

Het is overigens op toepassing by DIrectShow Applicaties waar er toch weer voor een vette C laag is gekozen ipv C++. wel te verstaan maar nu zit ik weer een wrapper te bouwen rond directshow voor alles toch wat handiger te hebben (tis voor x-video input library). Ik zit nu met een libary van +/- 5.000 regels code (C++ met CComPtr's en std:: -> lees dus korte code, zonder ook maar 1 copy/paste). In quicktime is hetzelfde in 100 regels (en de oude getrouwe VideoForWindow een 1.000 tal)...

Thx Mr & Ms :).