ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C++로 Aggregation 구현하기
    컴포넌트(COM)/Aggregation 2008. 11. 26. 22:18
    #include <objbase.h>

    interface ICalcu : IUnknown
    {
        virtual int __stdcall Sum(int x, int y) = 0;
        virtual int __stdcall Sub(int x, int y) = 0;
        virtual int __stdcall Mul(int x, int y) = 0;
        virtual double __stdcall Div(int x, int y) = 0;
    };

    interface IRadius : IUnknown
    {
        virtual double __stdcall Radius(int x, int y) = 0;
    };

    HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
                                               const IID& iid,
                                               void** ppv)
    {
        if(pUnknownOuter != NULL)
        {
            return CLASS_E_NOAGGREGATION;
        }

        CSimpleCalc2* pSc = new CSimpleCalc2;
        if(pSc == NULL)
        {
            return E_OUTOFMEMORY;
        }

        HRESULT hr = pSc->InitAggregation() ;
        if (FAILED(hr))
        {
            pSc->Release() ;
            return hr ;
        }

        /* HRESULT */hr = pSc->QueryInterface(iid,ppv);

        pSc->Release();

        return hr;
    }

    #include "interface.h"

    class CSimpleCalc2 : public IRadius 
    {
    public:
    ...
        HRESULT InitAggregation() ;

    private:
    ...
        IUnknown* m_pUnknownInner;
    };

    CSimpleCalc2::~CSimpleCalc2()
    {
        InterlockedDecrement(&g_cComponents);
    ...
        if (m_pUnknownInner != NULL)
        {
            m_pUnknownInner->Release() ;
        }
    }

    HRESULT CSimpleCalc2::InitAggregation()
    {
        IUnknown* pUnknownOuter = this;

        HRESULT hr = ::CoCreateInstance(CLSID_COMPONENT,
                                        pUnknownOuter,
                                        CLSCTX_INPROC_SERVER,
                                        IID_IUnknown,
                                        (void**)&m_pUnknownInner) ;
        if (FAILED(hr))
        {
            return E_FAIL ;
        }
    ...
        return S_OK ;
    }

    HRESULT __stdcall CSimpleCalc2::QueryInterface(const IID& iid, void** ppv)
    {
        if(iid == IID_IUnknown)
        {
            *ppv = static_cast<IRadius*>(this);
        }
        else if(iid == IID_IRadius)
        {
            *ppv = static_cast<IRadius*>(this);
        }
    // {
        else if (iid == IID_ICalcu)
        {
            return m_pUnknownInner->QueryInterface(iid,ppv) ;
        }
    // }
        else
        {
            *ppv = NULL;
            return E_NOINTERFACE;
        }

        static_cast<IUnknown*>(*ppv)->AddRef();

        return S_OK;
    }


    #include <objbase.h>

    interface ICalcu : IUnknown
    {
        virtual int __stdcall Sum(int x, int y) = 0;
        virtual int __stdcall Sub(int x, int y) = 0;
        virtual int __stdcall Mul(int x, int y) = 0;
        virtual double __stdcall Div(int x, int y) = 0;
    };

    HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
                                               const IID& iid,
                                               void** ppv)
    {
        if((pUnknownOuter != NULL)  && (iid != IID_IUnknown))
        {
            return CLASS_E_NOAGGREGATION;
        }

        CSimpleCalc* pSc = new CSimpleCalc(pUnknownOuter);
        if(pSc == NULL)
        {
            return E_OUTOFMEMORY;
        }

        HRESULT hr = pSc->NondelegatingQueryInterface(iid,ppv);

        pSc->NondelegatingRelease();

        return hr;
    }


    #include "interface.h"

    struct INondelegatingUnknown
    {
        virtual HRESULT __stdcall
            NondelegatingQueryInterface(const IID&, void**) = 0 ;
        virtual ULONG __stdcall NondelegatingAddRef() = 0 ;
        virtual ULONG __stdcall NondelegatingRelease() = 0 ;
    } ;

    class CSimpleCalc : public ICalcu, public INondelegatingUnknown
    {
    public:
        // IUnknown
        virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv)
        {
            return m_pUnknownOuter->QueryInterface(iid, ppv) ;
        }

        virtual ULONG   __stdcall AddRef()
        {
            return m_pUnknownOuter->AddRef() ;
        }

        virtual ULONG   __stdcall Release()
        {
            return m_pUnknownOuter->Release() ;
        }

        // Nondelegating IUnknown
        virtual HRESULT __stdcall NondelegatingQueryInterface(const IID& iid, void** ppv) ;
        virtual ULONG   __stdcall NondelegatingAddRef() ;
        virtual ULONG   __stdcall NondelegatingRelease() ;

        CSimpleCalc(IUnknown* pUnknownOuter);
    ...
        // ICalcu
        virtual int        __stdcall Sum(int x, int y)
        {
            return x + y;
        }

        virtual int        __stdcall Sub(int x, int y)
        {
            return x - y;
        }

        virtual int        __stdcall Mul(int x, int y)
        {
            return x * y;
        }

        virtual double    __stdcall Div(int x, int y)
        {
            return x / y;
        }

    private:
    ...
        IUnknown* m_pUnknownOuter;
    };


    #include "SimpleCalc.h"

    CSimpleCalc::CSimpleCalc(IUnknown* pUnknownOuter) : m_cRef(1)
    {
    ...
        if (pUnknownOuter == NULL)
        {
            m_pUnknownOuter = reinterpret_cast<IUnknown*>
                              (static_cast<INondelegatingUnknown*>
                              (this)) ;
        }
        else
        {
            m_pUnknownOuter = pUnknownOuter ;
        }
    }


    HRESULT __stdcall CSimpleCalc::NondelegatingQueryInterface(const IID& iid, void** ppv)
    {
        if(iid == IID_IUnknown)
        {
            *ppv = static_cast<INondelegatingUnknown*>(this);
        }
        else if(iid == IID_ICalcu)
        {
            *ppv = static_cast<ICalcu*>(this);
        }
        else
        {
            *ppv = NULL;
            return E_NOINTERFACE;
        }

        static_cast<IUnknown*>(*ppv)->AddRef();
        return S_OK;
    }

    ULONG __stdcall CSimpleCalc::NondelegatingAddRef()
    {
        return InterlockedIncrement(&m_cRef) ;
    }

    ULONG __stdcall CSimpleCalc::NondelegatingRelease()
    {
        if (InterlockedDecrement(&m_cRef) == 0)
        {
            delete this ;
            return 0 ;
        }
        return m_cRef ;
    }

Designed by Tistory.