Important: |
---|
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. |
DirectShow implements IUnknownin a base class called CUnknown. You can use CUnknownto derive other classes, overriding only the methods that change across components. Most of the other base classes in DirectShow derive from CUnknown, so your component can inherit directly from CUnknownor from another base class.
INonDelegatingUnknown
CUnknownimplements INonDelegatingUnknown. It manages reference counts internally, and in most situations your derived class can inherit the two reference-counting methods with no change. Be aware that CUnknowndeletes itself when the reference count drops to zero. On the other hand, you must override NonDelegatingQueryInterface, because the method in the base class returns E_NOINTERFACE if it receives any IID other than IID_IUnknown. In your derived class, test for the IIDs of interfaces that you support, as shown in the following example.
Copy Code | |
---|---|
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv) { if (riid == IID_ISomeInterface) { return GetInterface((ISomeInterface*)this, ppv); } // default return CUnknown::NonDelegatingQueryInterface(riid, ppv); } |
The utility function GetInterfacesets the pointer, increments the reference count in a thread-safe way, and returns S_OK. In the default case, call the base class method and return the result. If you derive from another base class, call its NonDelegatingQueryInterfacemethod instead. This enables you to support all the interfaces that the parent class supports.
IUnknown
As mentioned earlier, the delegating version of IUnknownis the same for every component, because it does nothing more than invoke the correct instance of the nondelegating version. For convenience, the header file Combase.h contains a macro, DECLARE_IUNKNOWN, which declares the three delegating methods as inline methods. It expands to the following code.
Copy Code | |
---|---|
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { return GetOwner()->QueryInterface(riid,ppv); }; STDMETHODIMP_(ULONG) AddRef() { return GetOwner()->AddRef(); }; STDMETHODIMP_(ULONG) Release() { return GetOwner()->Release(); }; |
The utility function GetOwnerretrieves a pointer to the IUnknowninterface of the component that owns this component. For an aggregated component, the owner is the outer component. Otherwise, the component owns itself. Include the DECLARE_IUNKNOWN macro in the public section of your class definition.
Class Constructor
Your class constructor should invoke the constructor method for the parent class, in addition to anything it does that is specific to your class. The following example is a typical constructor method.
Copy Code | |
---|---|
CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) : CUnknown(tszName, pUnk) { /* Other initializations */ }; |
The method takes the following parameters, which it passes directly to the CUnknownconstructor method.
-
tszNamespecifies a name for the component.
-
pUnkis a pointer to the aggregating
IUnknown.
-
pHris a pointer to an HRESULT value, indicating the success
or failure of the method.
Summary
The following example shows a derived class that supports IUnknownand a hypothetical interface named ISomeInterface .
Copy Code | |
---|---|
class CMyComponent : public CUnknown, public ISomeInterface { public: DECLARE_IUNKNOWN; STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv) { if( riid == IID_ISomeInterface ) { return GetInterface((ISomeInterface*)this, ppv); } return CUnknown::NonDelegatingQueryInterface(riid, ppv); } CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) : CUnknown(tszName, pUnk) { /* Other initializations */ }; // More declarations will be added later. }; |
This example illustrates the following points.
- The
CUnknownclass implements the
IUnknowninterface. The new component inherits from
CUnknownand from any interfaces that the component supports.
The component could derive instead from another base class that
inherits from
CUnknown.
- The DECLARE_IUNKNOWN macro declares the delegating
IUnknownmethods as inline methods.
- The
CUnknownclass provides the implementation for
INonDelegatingUnknown.
- To support an interface other than
IUnknown, the derived class must override the
INonDelegatingQueryInterfacemethod and test for the IID of
the new interface.
- The class constructor invokes the constructor method for
CUnknown.
The next step in writing a filter is to enable an application to create new instances of the component. This requires an understanding of DLLs and their relation to class factories and class constructor methods. For more information, see Creating a DLL in DirectShow.