Toon posts:

[WIN32/COM] Netjes afhandelen van COM QueryInterface etc. *

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben opzoek naar een handige functie of macro waarbij ik niet telkens het onderstaande hoef te doen...

code:
1
2
3
4
5
6
7
8
9
HRESULT hr;
hr = m_pObject->QueryInterface(IID_ISomeInterface, (void **) &m_pInterface);

if(FAILED(hr)) {
  m_pInterface = NULL;
  m_pObject->Release();
}

.......


Ik moet namelijk wel een stuk of 10 interface query's uitvoeren, wat natuurlijk een superranzige code meebrengt, plus veel redundante code om alle voorgaande interfaces te releasen.

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 19-05 21:24

NMe

Quia Ego Sic Dico.

Je kan toch zelf een functie schrijven die alle benodigde gegevens als input gebruikt? :?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Verwijderd

Topicstarter
Een functie schrijven om bovenstaande te doen is natuurlijk het probleem niet. Het gaat mij erom dat bij een fout alle voorgaande interfaces ge-released moeten worden.
Ik zit hierbij te denken aan een soort smart pointer die de interface die er aan vast zit released bij het decontructen van de instantie van de smart pointer.

Verwijderd

Je kan een functie bouwen die een object toetst op een verzameling van interfaces. Als de verzameling paren bevat van interface-ID met interface pointer, kan de functie de interface pointers netjes bijschrijven.

Aan deze functie kan je dan een extra parameter meegeven of er regeleased moet worden wanneer niet alle interfaces beschikbaar waren. Kies je hier voor "nee", dan heb je de mogelijkheid te kijken welke interfaces niet beschikbaar zijn.

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Kijk eens naar de ATL wrapper CComPtr. Die doet waarschijnlijk precies wat je wil.

Dan kan je code schrijven in de trant van:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void MyFunc(CComPtr<IUnknown> pUnk){
  CComPtr<IFinalInterface> pIFinal;
  try{
    CComPtr<IInterface1> pInterface1;
    CComPtr<IInterface2> pInterface2;
    CComPtr<IInterface3> pInterface3;
    CComPtr<IInterface4> pInterface4;
    HRESULT hr;

    hr = pUnk.QueryInterface(pInterface1);
    if(FAILED(hr)
      throw std::string("Can't get IInterface1");

    hr = pInterface1.QueryInterface(pInterface2);
    if(FAILED(hr)
      throw std::string("Can't get IInterface2");

    hr = pInterface2.QueryInterface(pInterface3);
    if(FAILED(hr)
      throw std::string("Can't get IInterface3");

    hr = pInterface3.QueryInterface(pInterface4);
    if(FAILED(hr)
      throw std::string("Can't get IInterface4");

    hr = pInterface4.QueryInterface(pIFinal);
    if(FAILED(hr)
      throw std::string("Can't get IFinalInterface");
  }catch(const std::string &sErr){
    //...
  }

}

[ Voor 86% gewijzigd door MrBucket op 17-11-2004 13:32 ]


Verwijderd

Topicstarter
Helaas krijg ik je voorbeeld niet aan de praat. Ik blijf steken op het gedeelte waar ik mijn COM Object moet instantieren.

Zou je een voorbeeld kunnen geven van het opvragen van een interface + het instantieren van een COM Object?

Ik moet namelijk ook meerdere objecten instantieren, het gaat om een reeks van directshow filters. Dit zijn er iig 4, en van elke filter moeten er ook nog een paar interfaces opgevraagd worden.

[ Voor 30% gewijzigd door Verwijderd op 17-11-2004 14:16 ]


Verwijderd

Topicstarter
Okay, ik heb de fout al ontdekt in je code, je gaf aan pUnk.QueryInterface een pointer mee, maar hij verwacht een pointer naar die pointer.

Zit nu alleen nog met het verbeteren van het instantieren van de COM Objecten, die tevens gereleased moeten worden nadat ze out-of-scope gaan.

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Verwijderd schreef op woensdag 17 november 2004 @ 14:37:
Okay, ik heb de fout al ontdekt in je code, je gaf aan pUnk.QueryInterface een pointer mee, maar hij verwacht een pointer naar die pointer.

Zit nu alleen nog met het verbeteren van het instantieren van de COM Objecten, die tevens gereleased moeten worden nadat ze out-of-scope gaan.
Oeps, my bad. Klopt, ik had die code ook even uit m'n hoofd getypt, zonder te testen :X

Wat het tweede punt betreft: ik snap je probleem niet helemaal. Kan ook aan je verwoording liggen, maar als het goed is krijg je nooit te maken met COM-objecten, maar alleen met de interfaces die het exposed. En zo lang je elke interface pointer opslaat in zo'n CComPtr-wrapper (in plaats van een 'normale' abstract base class pointer), moet het reference counten goed gaan, en worden de achterliggende objecten gedeleted waarneer alle relevante CComPtrs uit scope gaan.

Verwijderd

Topicstarter
Ik bedoelde het volgende:

code:
1
2
CComPtr<IUnknown> pObject;
CoCreateInstance(......., (void **) &pObject);


Vroeg me af of een dergelijke constructie ook mogelijk was...

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Verwijderd schreef op woensdag 17 november 2004 @ 15:26:
Ik bedoelde het volgende:

code:
1
2
CComPtr<IUnknown> pObject;
CoCreateInstance(......., (void **) &pObject);


Vroeg me af of een dergelijke constructie ook mogelijk was...
Jazeker. Heb je het niet geprobeerd? - Het hoort te werken ;)

Als ik me niet vergis heeft CComPtr de address-of operator & geoverload, zodat het een referentie naar de 'echte' interface-pointer teruggeeft, in plaats van het adres van het CComPtr-object.

--edit--
Ter info: dit gaat goed, omdat QueryInterface (of in dit geval CoCreateInstance, die QueryInterface gebruikt om de gevraagde interface te retourneren) verantwoordelijk is voor het incrementen van de reference count. Dus de CComPtr hoeft dit in dit geval niet zelf te doen (zoals wel gebeurt bij het kopieren van een CComPtr-object).

[ Voor 26% gewijzigd door MrBucket op 17-11-2004 16:58 ]

Pagina: 1