Re: IUnknown interface
On 15 Sep., 15:24, George <Geo...@discussions.microsoft.com> wrote:
Thanks dertopper,
I agree understand your point 1 and 2. But for 2, you mentioned below,
Imagine your COM component has implements two interfaces IA and IB,
both directly derived from IUnknown. The interface pointers for IA and
IB are different, so calling IA->AddRef and IB->AddRef can result in
two different implementations (note that usually both interface tables
point to the same method). This way you could provide a different
implementations of AddRef, depending on whether the client called
AddRef through the IA or the IB interface.
I find some conflicting in your points which make me confused.
You mentioned IA->AddRef and IB->AddRef are two different implementations?
But you also mentioned -- "usually both interface tables point to the same
method", I think same method means same item in vtable and it should be the
same implementation?
Could you show some pseudo code here to express please? Code makes everyone
clear. :-)
regards,
George
#include "unknwn.h"
#include <iostream>
class __declspec(uuid("63EBC97E-A3CF-464d-882F-6384B0062224"))
IA : public IUnknown
{
public:
virtual HRESULT DoSomething () = 0;
};
class __declspec(uuid("2ECC02CF-0D06-47ad-A6C7-0283E0D7D5DD"))
IB : public IUnknown
{
public:
virtual HRESULT DoSomethingElse () = 0;
};
class IAImpl : public IA
{
public:
IAImpl (IUnknown* pParent)
: m_pParent (pParent)
{}
HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void**
ppvObject)
{
return m_pParent->QueryInterface (riid, ppvObject);
}
ULONG STDMETHODCALLTYPE AddRef ()
{
std::cout << "AddRef of class A has been called.\n";
return m_pParent->AddRef ();
}
ULONG STDMETHODCALLTYPE Release ()
{
return m_pParent->Release ();
}
virtual HRESULT DoSomething ()
{
std::cout << "IA::DoSomething has been called.\n";
return S_OK;
}
private:
IUnknown* m_pParent;
};
class IBImpl : public IB
{
public:
IBImpl (IUnknown* pParent)
: m_pParent (pParent)
{}
HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void**
ppvObject)
{
return m_pParent->QueryInterface (riid, ppvObject);
}
ULONG STDMETHODCALLTYPE AddRef ()
{
std::cout << "AddRef of class B has been called.\n";
return m_pParent->AddRef ();
}
ULONG STDMETHODCALLTYPE Release ()
{
return m_pParent->Release ();
}
virtual HRESULT DoSomethingElse ()
{
std::cout << "IB::DoSomethingElse has been called.\n";
return S_OK;
}
private:
IUnknown* m_pParent;
};
class CSomeCoClassName : public IUnknown
{
protected:
IAImpl m_AImpl;
IBImpl m_BImpl;
public:
CSomeCoClassName ()
: m_ReferenceCount (1),
m_AImpl (this),
m_BImpl (this)
{}
HRESULT InternalQueryInterface (REFIID riid, void** ppvObject)
{
if (riid == __uuidof (IA) || riid == __uuidof (IUnknown))
{
*ppvObject = &m_AImpl;
AddRef ();
return S_OK;
}
if (riid == __uuidof (IB))
{
*ppvObject = &m_BImpl;
AddRef ();
return S_OK;
}
return E_NOTIMPL;
}
ULONG InternalAddRef ()
{
return ++m_ReferenceCount;
}
ULONG InternalRelease ()
{
int RetVal = --m_ReferenceCount;
if (RetVal == 0)
delete this;
return RetVal;
}
HRESULT STDMETHODCALLTYPE QueryInterface (REFIID riid, void**
ppvObject)
{
return InternalQueryInterface (riid, ppvObject);
}
ULONG STDMETHODCALLTYPE AddRef ()
{
std::cout << "AddRef of class CSomeCoClassName has been called.
\n";
return InternalAddRef ();
}
ULONG STDMETHODCALLTYPE Release ()
{
return InternalRelease ();
}
protected:
int m_ReferenceCount;
};
int main(int argc, char* argv[])
{
// Create a COM object by hand.
CSomeCoClassName* SomeCoClassInstance = new CSomeCoClassName ();
IA* pA;
// Retrieve the interface pointers for interfaces IA and IB.
HRESULT hr = SomeCoClassInstance->QueryInterface (__uuidof (IA),
(void**)&pA);
if (!SUCCEEDED (hr))
return 1;
IB* pB;
hr = SomeCoClassInstance->QueryInterface (__uuidof (IB),
(void**)&pB);
if (!SUCCEEDED (hr))
return 1;
// Increment and decrement reference count through interface IB.
pB->AddRef ();
pB->Release ();
// Increment and decrement reference count through interface IA.
pA->AddRef ();
pA->Release ();
// Release everything.
pB->Release ();
pA->Release ();
SomeCoClassInstance->Release ();
return 0;
}
Regards,
Stuart