Essential COM

, C++. , C++, , QueryInterface. . , , , DLL, . , , ( 1). , .

, , ICar:

 class Car : public ICar {      LONG m_cRef;     Car(void) : m_cRef(0) {}     STDMETHODIMP QueryInterface(REFIID, void **);     STDMETHODIMP_(ULONG) AddRef(void);     STDMETHODIMP_(ULONG) Release(void);     STDMETHODIMP GetMaxSpeed(long *pn);     STDMETHODIMP Brake(void); }; STDMETHODIMP Car::QueryInterface(REFIID riid, void **ppv)  {     if (riid == IID_IUnknown)         *ppv = static_cast<IUnknown*>(this);     else if (riid == IID_IVehicle)         *ppv = static_cast<IVehicle*>(this);     else if (riid == IID_ICar)         *ppv = static_cast<ICar*>(this);     else         return (*ppv = 0), E_NOINTERFACE;     ((IUnknown*)*ppv)->AddRef();     return S_OK; } // car class object's IClassFactory::CreateInstance //   IClassFactory::CreateInstance //     car STDMETHODIMP CarClass::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) {     Car *pCar = new Car;     if (*pCar)          return (*ppv = 0), E_OUTOFMEMORY;     pCar->AddRef();     HRESULT hr = pCar->QueryInterface(riid, ppv);     pCar->Release();     return hr; } 

QueryInterface, AddRef Release.

C++, Car :

 class CarBoat : public IBoat {     LONG m_cRef;     Unknown *m_pUnkCar;     CarBoat(void);     virtual ~CarBoat(void);     STDMETHODIMP QueryInterface(REFIID, void **);     STDMETHODIMP_(ULONG) AddRef(void);     STDMETHODIMP_(ULONG) Release(void);     STDMETHODIMP GetMaxSpeed(long *pn);     STDMETHODIMP Sink(void); }; 

Car, :

 CarBoat::CarBoat (void) : m_cRef(0)  {     HRESULT hr = CoCreateInstance(CLSID_Car, 0, CLSCTX_ALL,                                    IID_IUnknown, (void**)&m_pUnkCar);     assert(SUCCEEDED(hr)); } CarBoat::~CarBoat(void)  {     if (m_pUnkCar)          m_pUnkCar->Release(); } 

QueryInterface:

 STDMETHODIMP CarBoat::QueryInterface(REFIID riid, void **ppv)  {     if (riid == IID_IUnknown)         *ppv = static_cast<IUnknown*>(this);     else if (riid == IID_IVehicle)         *ppv = static_cast<IVehicle*>(this);     else if (riid == IID_IBoat)         *ppv = static_cast<IBoat*>(this);     else if (riid == IID_ICar)       // forward request...       //    ...         return m_pUnkCar->QueryInterface(riid, ppv);     else         return (*ppv = 0), E_NOINTERFACE;     ((IUnknown*)*ppv)->AddRef();     return S_OK; } 

Car , (identity) , QueryInterface IBoat. ,

 QI(IBoat)->ICar  

,

 QI(QI(IBoat)->ICar)->IBoat 

, QueryInterface . QueryInterface IUnknown ICar IBoat , , . IUnknown , CarBoat .

. , , . QueryInterface - . - , ( ) ( ). - IUnknown, (identity) .

. . - . :

 class Handlebar : public IHandlebar { ... }; class Wheel : public IWheel {}; class Bicycle : public IBicycle {      IHandlebar * m_pHandlebar;     IWheel *m_pFrontWheel;     IWheel *m_pBackWheel; } 

icycle IHandlebar ( ) IWheel ( ) QueryInterface. QueryInterface " " (is-a), (bicycle) (wheel) (handlebar). Bicycle , IBicycle :

 [object, uuid(753A8A60-A7FF-11d0-8C30-0080C73925BA)] interface IBicycle : IVehicle {     HRESULT GetHandlebar([out,retval] IHandlebar **pph);     HRESULT GetWheels([out] IWheel **ppwFront, [out] IWheel **ppwBack); } 

Bicycle :

 STDMETHODIMP Bicycle::GetHandlebar(IHandlebar **pph) {     if (*pph = m_pHandlebar)         (*pph)->AddRef();     return S_OK; } STDMETHODIMP Bicycle::GetWheels(IWheel **ppwFront, IWheel **ppwBack) {     if (*ppwFront = m_pFrontWheel)          (*ppwFront)->AddRef();     if (*ppwBack = m_pBackWheel)          (*ppwBack)->AddRef();     return S_OK; } 

- . , QueryInterface, .

, , , . , - , ( ) , . , (creation function), , : IUnknown , QueryInterface, AddRef Release. CreateInstance IClassFactory:

 HRESULT CreateInstance([in] Unknown *pUnkOuter,                        [in] REFIID riid, [out, iid_is(riid)] void **ppv); 

( API- CoCreateInstanceEx CoCreateInstance) (stand-alone) . CreateInstance (pUnkOuter), . , , pUnkOuter. QueryInterface, AddRef Release pUnkOuter. .

, , CarBoat :

 CarBoat::CarBoat(void) : m_cRef(0) {       // need to pass identity of self to Create routine       // to notify car object it 1s an aggregate       //                // Create       car,     -      HRESULT hr = CoCreateInstance(CLSID_Car, this,                          CLSCTX_ALL, IID_IUnknown, (void**)&m_pUnkCar);     assert(SUCCEEDED(hr)); } 

CarBoat QueryInterface ICar :

 STDMETHODIMP CarBoat::QueryInterface(REFIID riid, void **ppv) {      if (riid == IID_IUnknown)          *ppv = static_cast<IUnknown*>(this);     else if (riid == IID_ICar)         // forward request...         //    ...         return m_pUnkCar->QueryInterface(riid, ppv);     else if (riid == IID_IBoat)     :    :    : 

, QueryInterface , .

CreateInstance Car , IUnknown. IUnknown , : 1) , ; 2) . QueryInterface , , .

, , , IUnknown . , , - , IUnknown. , , QueryInterface, AddRef Release . , vtbl , , . IUnknown, .

IUnknown . 1 IUnknown. Car, :

 class Car : public ICar {     LONG m_cRef;     IUnknown *m_pUnk0uter;   public:     Car(IUnknown *pUnk0uter);       // non-delegating IUnknown methods        //     IUnknown      STDMETHODIMP InternalQueryInterface(REFIID, void **);     STDMETHODIMP (ULONG) InternalAddRef(void);     STDMETHODIMP_(ULONG) InternalRelease(void);       // delegating IUnknown methods       //     IUnknown     STDMETHODIMP QueryInterface(REFIID, void **);     STDMETHODIMP_(ULONG) AddRef(void);     STDMETHODIMP_(ULONG) Release(void);     STDMETHODIMP GetMaxSpeed(*long *pn);     STDMETHODIMP Brake(void);       // composite to map distinguished IUnknown vptr to       // non-delegating InternalXXX routines 1n main object       //         vptr IUnknown       //       InternalXXX          //      class XNDUnknown : public IUnknown {         Car* This()            { return (Car*)((BYTE*)this - offsetof(Car, m_innerUnknown));}          STDMETHODIMP QueryInterface(REFIID r, void**p)            { return This()->InternalQueryInterface(r,p); }          STDMETHODIMP_(ULONG) AddRef(void)            { return This()->InternalAddRef(); }          STDMETHODIMP_(ULONG) Release(void)            { return This()->InternalRelease(); }     };     XNDUnknown m_innerUnknown;       // composite instance        //      }; 

. 4.8. :

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

 . 4.8.   car

, vtbl , , IUnknown .

m_pUnkOuter , IUnknown:

 Car::Car(IUnknown *pUnkOuter) {     if (pUnkOuter)       // delegate to pUnkOuter        //     pUnkOuter         m_pUnkOuter = pUnkOuter;     else       // delegate to non-delegating self        //                m_pUnkOuter = &m_innerUnknown; } 

, m_pUnkOuter QueryInterface, AddRef Release.

QueryInterface, AddRef Release :

 STDMETHODIMP Car::InternalQueryInterface(REFIID riid, void **ppv)  {     if (riid == IID_IUnknown)         *ppv = static_cast<IUnknown*>(&m_innerUnknown);     else if (riid = IID_IVehicle)         *ppv = static_cast<IVehicle*>(this);     else if (riid == IID_ICar)         *ppv = static_cast<ICar*>(this);     else         return (*ppv = 0), E_NOINTERFACE;     ((IUnknown*)*ppv)->AddRef();     return S_OK; }  STDMETHODIMP_(ULONG) Car::InternalAddRef(void)  {     return InterlockedIncrement(&m_cRef); }  STDMETHODIMP_(ULONG) Car::InternalRelease(void) {     ULONG res = InterlockedDecrement(&m_cRef);     if (res == 0) delete this;     return res; } 

( ) , InternalQueryInterface IUnknown Unknown. , .

, Car :

 STDMETHODIMP CarClass::CreateInstance(IUnknown *punk0uter, REFIID riid, void **ppv) {       // verify that aggregator only requests IUnknown as       // initial interface        //  ,         IUnknown        //          if (pUnkOuter != 0 && riid != IID_IUnknown)         return (*ppv = 0), E_INVALIDARG;       // create new object/aggregate        //              Car *  = new Car(pUnkOuter);     if (!p) return (*ppv = 0), E_OUTOFMEMORY;       // return resultant pointer       //          p->InternalAddRef();     HRESULT hr = p->InternalQueryInterface(riid, ppv);     p->InternalRelease();     return hr; } 

, QueryInterface, AddRef Release. , , , . , , AddRef , . , IUnknown. . , vptr: QueryInterface, AddRef Release, . IUnknown vptr, IUnknown.

- , . , , AddRef. AddRef , AddRef, . , IUnknown ( , ) . IUnknown . . - , . , (identities) , .

, . , QueryInterface IUnknown. QueryInterface AddRef , AddRef. , , AddRef. , . , , :

 STDMETHODIMP Inner::MethodX(void)  {     ITruck *pTruck = 0;       // outer object will be AddRefed after this call...        //                      //     AddRef...      HRESULT hr = m_pUnkOuter->QueryInterface(IID_ITruck, (void**)&pTruck);     if (SUCCEEDED(hr)) {          pTruck->ShiftGears();         pTruck->HaulDirt();           // release reference to outer object            //                    pTruck->Release();     }  } 

, .

 HRESULT Inner::Initialize(void)  {     // outer object will be AddRefed after this call...      //                    //     AddRef...      HRESULT hr = m_pUnkOuter->QueryInterface(IID_ITruck, (void**)&m_pTruck);     // release reference to outer object here and DO NOT      // release it later in the object's destructor      //                    //                    if (SUCCEEDED(hr))          m_pTruck->Release(); } 

, . , m_pTruck . , ITruck , , Release .

, , , . , . , . , . , QueryInterface, AddRef , . , , , , , . , , , :

 Outer::Outer(void)  {     ++m_cRef;       // protect against delete this       //       this     CoCreateInstance(CLSID_Inner, this, CLSCTX_ALL,                       IID_IUnknown, (void**)&m_pUnkInner);     --m_cRef;       // allow delete this       //     this } 

, , , , . , - (overridable), / . MFC (Microsoft Foundation Classes Microsoft) CreateAggregates, ATL FinalConstruct.

, C++, IMPLEMENT_UNKNOWN IUnknown. :

 class Car : public ICar {     Car(void);     IMPLEMENT_UNKNOWN(Car)      BEGIN_INTERFACE_TABLE(Car)     IMPLEMENTS_INTERFACE(ICar)     IMPLEMENTS_INTERFACE(IVehicle)     END_INTERFACE()       // IVehicle methods        //   IVehicle      STDMETHODIMP GetMaxSpeed(long *pn);       // ICar methods        //   ICar      STDMETHODIMP Brake(void); }; 

:

 class Car : public ICar {     Car(void);      //indicate that aggregation is required       //  ,            IMPLEMENT_AGGREGATABLE_UNKNOWN(Car)      BEGIN_INTERFACE_TABLE(Car)       IMPLEMENTS_INTERFACE(ICar)       IMPLEMENTS_INTERFACE(IVehicle)      END_INTERFACE()       // IVehicle methods        //   IVehicle      STDMETHODIMP GetMaxSpeed(long *pn);       // ICar methods        //   ICar      STDMETHODIMP Brake(void); }; 

IMPLEMENT_AGGREGATABLE_UNKNOWN , .


1 , (coloring) IUnknown. , , .



Suschnost' tehnologii SOM
Essential COM
ISBN: 0201634465
EAN: 2147483647
Year: N/A
Pages: 103
Authors: Don Box

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net