DirectShow -- Verwendung von CUnknown



  • hallo,

    bitte um hilfe, ich kenn mich nicht mehr aus -- kleines (naja, etwas untertrieben) verständnisproblem bei der implementierung von IUnknown mithilfe von CUnknown:

    angenommen, ich möchte ein IOverlayNotify interaface implementieren. wie mach' ich das. ich hab gleich mal gemerkt, dass IOverlayNotify von IUnknown erbt, dafür muss ich also die methoden AddRef, Release und QueryInterface implementieren. nachdem ich keinen plan hab, was da die com-runtime wieder im hintergrund macht von wegen proxy/stub/interprozess-dingens... dachte ich, ich befolge mal den rat der DirectShow doku, CUnknown zu verwenden. gut, also ich leite meine klasse von CUnknown ab, verwende DECLARE_IUNKNOWN als implementierung der IUnknown-Methoden und überlade NonDelegatingQueryInterface entsprechend.

    soweit alles klar. nur: wie erzeuge ich jetzt das teil? ich wollte doch ursprünglich nur ein callback-objekt für die Overlay-Events haben -- jetzt habe ich ein COM-objekt, das ich nicht mehr durchschaue, von dem ich nicht mehr weiß, wie ich an eine instanz ran komme und das

    1. (laut kommentar in combase.h) eine factory braucht, um erzeugt zu werden (von der com-runtime? mit CoCreateInstance oder wie? braucht die klasse dann auch eine GUID?)
    2. einen IUnknown-pointer auf den parent braucht -- welcher parent wäre denn das dann in meinem fall? *confused* laut msdn wäre das das objekt selbst.

    msdn schrieb:

    For an aggregated component, the owner is the outer component. Otherwise, the component owns itself.

    wenn das stimmen würde, dann würde sich die implementierung von DECLARE_IUNKNOWN relativ schnell in einer endlosschleife befinden, oder nicht?

    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
     		return GetOwner()->QueryInterface(riid,ppv);
    	};
    	STDMETHODIMP_(ULONG) AddRef() {
    		return GetOwner()->AddRef();
    	};
    
    	STDMETHODIMP_(ULONG) Release() {
    		return GetOwner()->Release();
    	};
    

    ich wäre sehr dankbar, wenn jemand etwas licht in die sache bringen könnte. danke. bitte mit kurzem beispiel, meinetwegen pseudocode, hauptsache, ich weiß worums geht. und ja, ich habe gegoogelt.



  • angenommen, ich möchte ein IOverlayNotify interaface implementieren. wie mach' ich das. ich hab gleich mal gemerkt, dass IOverlayNotify von IUnknown erbt, dafür muss ich also die methoden AddRef, Release und QueryInterface implementieren. nachdem ich keinen plan hab, was da die com-runtime wieder im hintergrund macht von wegen proxy/stub/interprozess-dingens... dachte ich, ich befolge mal den rat der DirectShow doku, CUnknown zu verwenden. gut, also ich leite meine klasse von CUnknown ab, verwende DECLARE_IUNKNOWN als implementierung der IUnknown-Methoden und überlade NonDelegatingQueryInterface entsprechend.

    Genau.

    soweit alles klar. nur: wie erzeuge ich jetzt das teil? ich wollte doch ursprünglich nur ein callback-objekt für die Overlay-Events haben -- jetzt habe ich ein COM-objekt, das ich nicht mehr durchschaue, von dem ich nicht mehr weiß, wie ich an eine instanz ran komme und das

    1. (laut kommentar in combase.h) eine factory braucht, um erzeugt zu werden (von der com-runtime? mit CoCreateInstance oder wie? braucht die klasse dann auch eine GUID?)

    Ganz genau. Die Komponente muss eine eindeutige CLSID/GUID haben. Das Ganze machst du dann mit regsvr32 auch dem Rest des Systems bekannt.

    1. einen IUnknown-pointer auf den parent braucht -- welcher parent wäre denn das dann in meinem fall? *confused* laut msdn wäre das das objekt selbst.
      msdn schrieb:
      For an aggregated component, the owner is the outer component. Otherwise, the component owns itself.
      wenn das stimmen würde, dann würde sich die implementierung von DECLARE_IUNKNOWN relativ schnell in einer endlosschleife befinden, oder nicht?

    Du musst zwischen dem einen IUNKNOWN das nach "aussen" hin sichtbar (genau eines!) ist und den IUNKNOWNs welche du durch veerbung erhalten hast unterscheiden ("innen"). (ist so ähnlich wie virtual inheritance)
    Im Prinzip wird von "innen" nach "aussen" delegiert und am Ende steht dann ein nicht weiterdelegiertes (INonDelegatingUnknown) IUNKNOWN.

    WX



  • vielen dank erstmal.

    wie mache ich ein einzelnes COM-objekt, das ich innerhalb meiner applikation verwende, mit regsvr32 bekannt? dazu müsste ich es doch in eine dll kapseln, die NUR dieses objekt mit dazugehörigen RegisterServer/UnregisterServer-funktionen enthält, oder nicht? muss ich denn wirklich JEDES objekt, das IUnknown implementiert im system registrieren -- auch wenn ich es nur innerhalb des selben prozesses für debugging-zwecke verwende um ein paar meldungen auf die console raus zu schreiben? sorry, wenn ich das nochmals anzweifle, aber das klingt für mich so absurd, dass es mir schwer fällt, das zu akzeptieren... vielleicht war's ja ein missverständnis: also ich brauche das objekt NUR intern und kann es im notfall auch selbst erzeugen, wenn das irgendwie ohne größere umstände möglich ist (nochmals stichwort factory... den teil der kommentare hab ich nicht ganz verstanden -- in combase.h von den DirectShow BaseClasses gibts ja dieses CFactoryTemplate).

    WeaponX2007 schrieb:

    Du musst zwischen dem einen IUNKNOWN das nach "aussen" hin sichtbar (genau eines!) ist und den IUNKNOWNs welche du durch veerbung erhalten hast unterscheiden ("innen"). (ist so ähnlich wie virtual inheritance)
    Im Prinzip wird von "innen" nach "aussen" delegiert und am Ende steht dann ein nicht weiterdelegiertes (INonDelegatingUnknown) IUNKNOWN.

    hm, das versteh ich nicht. wo kommen denn die NonDelegating*-Methoden ins spiel? ich finde nicht heraus, wo die aufgerufen werden... ich habe folgende hierarchie:

    OverlayNotifyImpl
    | [i]QueryInterface()[/i]              -- GetOwner()->QueryInterface()
    | [i]AddRef()[/i]                      -- GetOwner()->AddRef()
    | [i]Release()[/i]                     -- GetOwner()->Release()
    | [i]NonDelegatingQueryInterface()[/i] -- CUnknown::NonDelegatingQueryInterface()
    |
    |-IOverlayNotify
    | |
    | |-IUnknown
    |
    |-CUnknown
      | [i]GetOwner()[/i]
      | [i]NonDelegatingQueryInterface()[/i]
      | [i]NonDelegatingAddRef()[/i]
      | [i]NonDelegatingRelease()[/i]
      |
      |-INonDelegatingUnknown
      |-CBaseObject
    

    wenn ich jetzt ein OverlayNotifyImpl erzeuge und in einem IUnknown-pointer speichere, dann AddRef aufgerufen wird, wird innerhalb dieser AddRef() vom owner-objekt aufgerufen. und GetOwner von CUnknown liefert in dem fall ja eben this, oder nicht? also rufe ich wieder die selbe methode auf und bin in 'ner endlosschleife (?)



  • wie mache ich ein einzelnes COM-objekt, das ich innerhalb meiner applikation verwende, mit regsvr32 bekannt? dazu müsste ich es doch in eine dll kapseln, die NUR dieses objekt mit dazugehörigen RegisterServer/UnregisterServer-funktionen enthält, oder nicht? muss ich denn wirklich JEDES objekt, das IUnknown implementiert im system registrieren -- auch wenn ich es nur innerhalb des selben prozesses für debugging-zwecke verwende um ein paar meldungen auf die console raus zu schreiben? sorry, wenn ich das nochmals anzweifle, aber das klingt für mich so absurd, dass es mir schwer fällt, das zu akzeptieren

    Du musst natürlich nur die Komponente registrieren und nicht jede Klasse die IUnknown implementiert. Das ganze natürlich in einer DLL mit DllRegisterServer/DllUnRegisterServer.

    vielleicht war's ja ein missverständnis: also ich brauche das objekt NUR intern und kann es im notfall auch selbst erzeugen, wenn das irgendwie ohne größere umstände möglich ist (nochmals stichwort factory... den teil der kommentare hab ich nicht ganz verstanden -- in combase.h von den DirectShow BaseClasses gibts ja dieses CFactoryTemplate).

    Wenn du es nur intern verwenden willst und nichts nach aussem exponierst, kannst natürlich ganz normal deine Objekte erzeugen. (hat ja dann auch nix mehr mit COM zu tun)

    hm, das versteh ich nicht. wo kommen denn die NonDelegating*-Methoden ins spiel? ich finde nicht heraus, wo die aufgerufen werden

    Das NonDelegatingQueryInterface ist an der Klasse die auch mit CreateInstance erzeugt wird (wieder QueryInterface Delegation). Das ist der Teil den du auch im CFactoryTemplate angibst. Aufgerufen wird das ganze vom der erstellenden Instanz. (Also jenem der CoCreateInstance aufruft)

    z.b.

    CFactoryTemplate g_Templates[] = 
    {
    	{
    		g_FilterName,
    			&CLSID_SomeClass,
    			CSomeClass::CreateInstance,  <--- HIER!
    			NULL,
    			&AMSFilterSomeClass
    	},
    	{
    		g_PropertyPageName,
    			&CLSID_SomeClass_PropertyPage,
    			CDebugSettings::CreateInstance,
    			NULL,
    			NULL
    		}
    };
    

    Sofern alles consistent ist trägt das Macro AMovieDllRegisterServer2 deine Komponente in die Registry ein.


Log in to reply