Wie findet eine ATL-Klasse ihre eigene IUnknown-Schnittstelle heraus?



  • Der Titel sagt eigentlich schon alles.
    Bei der Aggregation von ATL-Klassen ist es ja nötig, dass die äußere Klasse der inneren Klasse einen Zeiger auf ihre IUnknown-Schnittstelle übergibt (im Aufruf der CoCreateInstance(...) Methode).
    Nur wie bekommt eine Klasse eine Zeiger auf die eigene IUnknown-Schnittstelle?

    Ist wahrscheinlich ziemlich trivial, aber sowohl meine Bücher, als auch die Internetquellen, die ich zum COM Themen gefunden habe schweigen sich zum Thema Aggregation ziemlich aus (bis auf die Information, dass sie möglich ist).



  • Über QueryInterface :p
    Intern macht die ATL nichts anderes als den this pointer zurück liefern.



  • Das hab ich probiert, bekomme aber einen Compilerfehler. Knkret hab ich folgenden Code:

    class ATLKlasse {
    private:
       LPUNKNOWN* IUnknownSelbst;
    public:
       ATLKlasse() {
          QueryInterface(IUnknown, (void**)&IUnknownSelbst);
       //.....
    }
    

    Das funktioniert aber nicht.



  • würde mal spontan auf folgendes tippen:
    LPUNKNOWN -> IUnkown*
    LPUNKNOWN* -> IUnkown** (IUnknownSelbst)
    &IUnknownSelbst -> IUnkown*** (ein pointer zu viel 🤡 )



  • Ich glaube nicht, dass das was damit was zu tun hat. "IUnknown" in der QueryInterface-Methode ist ja keine Variable bzw. ein Pointer auf irgendwas, sondern ein Interfacebezeichner (REFIID). Aber vielleicht hab ich Deine Antwort nur falsch verstanden. um es noch ein wenig zu konkretisieren hab ich hier die korrekte Klassendefinition und die Fehlermeldung, die der Compiler ausgibt:

    class ATL_NO_VTABLE ATLKlasse : public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<ATLKlasse, &CLSID_ATLKlasse>, 
    public IConnectionPoint<ContainerImpl<ATLKlasse>, 
    public IDispatchImpl<ATLKlasse, &IID_ATLKlasse, &LIBID_ProjektLib> 
    {
       //wie gehabt siehe oben.
    

    Der Compiler gibt als Fehler folgendes aus:

    Kompilierung läuft...
    ATLKlasse.cpp
    D:\Software Developement\C++ Programme\Projekt\ATLKlasse.cpp(11) : error C2039: 'IUnknown' : Ist kein Element von 'IDispatch'
    c:\programme\microsoft visual studio\vc98\include\oaidl.h(2694) : Siehe Deklaration von 'IDispatch'
    D:\Software Developement\C++ Programme\Projekt\ATLKlasse.cpp(11) : error C2385: Mehrdeutiger Zugriff von '<unbekannt>' in 'operator`__restrict volatile signed ''
    D:\Software Developement\C++ Programme\Projekt\ATLKlasse.cpp(11) : warning C4385: 'kann sein 'IUnknown' in Basisklasse 'IConnectionPointContainer' of base 'IConnectionPointContainerImpl<class ATLKlasse>' of class 'ATLKlasse'
    D:\Software Developement\C++ Programme\Projekt\ATLKlasse.cpp(11) : warning C4385: 'oder 'IUnknown' in Basisklasse 'IDispatch' of base 'IATLKlasse' of base 'IDispatchImpl<struct IATLKLasse,&struct _GUID const IID_IATLKlasse,&struct _GUID const LIBID_ProjektLib,1,0,class ATL::CComTypeInfoHolder>' of class 'ATLKlasse'
    Fehler beim Ausführen von cl.exe.

    Projekt.exe - 2 Fehler, 2 Warnung(en)

    Das Problem scheint also zu sein, dass der Comiler nicht weiß, welche IUnknown-Schnittstelle er suchen soll (mehrdeutige Angabe). Die Frage ist, was muß man angeben, damit es eindeutig ist?

    EDIT: OK, ich weiß, was Du gemeint hast mit dem letzten Post. Hab den Fehler mit dem Pointer zuviel behoben, aber das Problem besteht immer noch.

    EDIT EDIT:
    Könnte das vielleicht richtig sein:

    IUnknownSelbst = static_cast<IDispatch*>(this);
    

    Also zeigt der this-Zeiger automatisch auf die IUnknownSchnittstelle?



    QueryInterface(IUnknown, (void**)&IUnknownSelbst);

    a) pointer -> ist gefixt
    b) Der erste paremeter ist ne uuid
    Diese Zeile sieht so richtig aus:

    QueryInterface(__uuidof(IUnknown), (void**)IUnknownSelbst);
    
    1. Das dein cast funktioniert bezweifle ich, da IDispatch nicht IUnknown erbt 😉

    Die IUnknown-methoden stehen in ner IDispatch klasse zwar auch am anfang der vtable, ein cast von einem interface in ein anderes immer aber gefährlich. Um das sicher hin zu bekommen gibt es QueryInterface 😉

    Also zeigt der this-Zeiger automatisch auf die IUnknownSchnittstelle?

    Der this zeiger ist die instanz deiner klasse, wenn deine klasse von IUnkown erbt zeigt er auf ne IUnkown instanz, klint logisch oder? 🤡
    Blöde farge am schluß: warum machst du das über nen IUnknown pointer wenn du von IDispatch erbst?


Anmelden zum Antworten