• com学习4——聚合


    聚合在com中的作用非常大,它是代码重用中最有效的模型。但是聚合也是比较麻烦的,因为跟包含一样,com对象B要屏蔽掉com对象A,即用户根本不知道com对象A的存在。但是用户却直接使用了com对象A的接口,通过接口的queryinterface函数是可以查找到com对象实现的所有接口,因为用户只知道com对象B的存在,对于用户来说,通过接口的queryinterface查询的结果应该都是com对象B支持的所有接口,而不应该查到com对象A的接口。因此内部要有很多的细节来处理这个。这里主要是com对象A需要处理,它需要多继承一个接口类,原来的那个接口类用来聚合用,而另外一个接口则是用于原本的功能。在下面的例子中会提到。例子用到了com对象A,com对象B以及调用程序,com对象A实现了接口ISomeInterface,com对象B实现了接口IOtherInterface,聚合了com对象A的接口ISomeInterface。
    例子:
    com对象A

    代码:
    接口:ISomeInterface.h
    #ifndef __ISomeInterface_H__
    #define __ISomeInterface_H__
     
    #include "Unknwn.h"
     
    extern "C" const GUID IID_SomeInterface;
     
    class ISomeInterface : public IUnknown
    {
    public:
    virtual int __stdcall Somefunction() = 0;
    };
     
    #endif
     
    对象:4_A.h
    #ifndef __4_A_H__
    #define __4_A_H__
     
    #ifndef __ISomeInterface_H__
    #include "ISomeInterface.h"
    #endif
     
    class INondelegatingUnknown
    {
    public:
    virtual HRESULT __stdcall NondelegatingQueryInterface(const IID& iid, void** ppv) = 0;
    virtual ULONG __stdcall NondelegatingAddRef() = 0;
    virtual ULONG __stdcall NondelegatingRelease() = 0;
    };
     
    class CA : public ISomeInterface, public INondelegatingUnknown
    {
    protected:
    ULONG m_Ref;
     
    public:
    CA(IUnknown* pUnknownOuter);
    ~CA();
     
    public:
    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
    virtual ULONG __stdcall AddRef();
    virtual ULONG __stdcall Release();
     
     
    virtual HRESULT __stdcall NondelegatingQueryInterface(const IID& iid, void** ppv);
    virtual ULONG __stdcall NondelegatingAddRef();
    virtual ULONG __stdcall NondelegatingRelease();
     
     
    virtual BOOL __stdcall Somefunction();
     
    private:
    IUnknown* m_pUnknownOuter;
    };
     
    #endif
     
    4_A.cpp
    #include "stdafx.h"
    #include <comutil.h>
    #include <stdio.h>
    #include "objbase.h"
    #include "olectl.h"
     
    #include "4_A.h"
    #include "Factory.h"
    #include "Registry.h"
     
    ULONG g_LockNumber = 0;
    ULONG g_4_ANumber = 0;
    HANDLE g_hModule;
     
     
     
    // {753E2E9D-7ACF-423F-AE87-710D88EEFD42}
    extern "C" const GUID CLSID_4_A =
    { 0x753e2e9d, 0x7acf, 0x423f,
    { 0xae, 0x87, 0x71, 0xd, 0x88, 0xee, 0xfd, 0x42 } };
    extern "C" const GUID IID_SomeInterface =
    { 0x753e2e9e, 0x7acf, 0x423f,
    { 0xae, 0x87, 0x71, 0xd, 0x88, 0xee, 0xfd, 0x42 } };
     
     
    BOOL APIENTRY DllMain( HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    g_hModule = hModule;
     
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }
     
     
    extern "C" HRESULT __stdcall DllGetClassObject(const CLSID& clsid, const IID& iid, void **ppv)
    {
    if (clsid == CLSID_4_A) {
     
    CAFactory *pFactory = new CAFactory;
     
    if (pFactory == NULL)
    {
    return E_OUTOFMEMORY ;
    }
     
    HRESULT result = pFactory->QueryInterface(iid, ppv);
     
    return result;
    }
    else return CLASS_E_CLASSNOTAVAILABLE;
    }
     
    extern "C" HRESULT __stdcall DllCanUnloadNow(void)
    {
    if ((g_4_ANumber == 0) && (g_LockNumber == 0)) return S_OK;
    else return S_FALSE;
    }
     
    extern "C" HRESULT __stdcall DllRegisterServer()
    {
    char szModule[1024];
    DWORD dwResult = ::GetModuleFileName((HMODULE)g_hModule, szModule, 1024);
    if (dwResult == 0) return SELFREG_E_CLASS;
    return RegisterServer(CLSID_4_A, szModule, "4_A.Object", "4_A Component", NULL);
    }
     
     
    extern "C" HRESULT __stdcall DllUnregisterServer()
    {
    return UnregisterServer(CLSID_4_A, "4_A.Object", NULL);
    }
     
     
    CA::CA(IUnknown* pUnknownOuter)
    {
    m_Ref = 0;
    g_4_ANumber++;
    m_pUnknownOuter = pUnknownOuter;
    }
     
    CA::~CA()
    {
     
    }
     
    ULONG CA::NondelegatingAddRef()
    {
    m_Ref++;
    return (ULONG) m_Ref;
    }
     
    ULONG CA::NondelegatingRelease()
    {
    m_Ref--;
    if(m_Ref == 0)
    {
    g_4_ANumber--;
    delete this;
    return 0;
    }
     
    return (ULONG) m_Ref;
    }
     
    HRESULT CA::NondelegatingQueryInterface(const IID& iid, void** ppv)
    {
    if(iid == IID_IUnknown)
    {
    *ppv = (INondelegatingUnknown*) this;
    //((INondelegatingUnknown*)(*ppv))->NondelegatingAddRef();
    ((IUnknown*)(*ppv))->AddRef();
    }
    else if(iid == IID_SomeInterface)
    {
    *ppv = (ISomeInterface*) this;
    ((ISomeInterface*)(*ppv))->AddRef();
    }
    else
    {
    *ppv = NULL;
    return E_NOINTERFACE;
    }
     
    return S_OK;
    }
     
     
    ULONG CA::AddRef()
    {
    if(m_pUnknownOuter != NULL) return m_pUnknownOuter->AddRef();
    else return NondelegatingAddRef();
    }
     
    ULONG CA::Release()
    {
    if(m_pUnknownOuter != NULL) return m_pUnknownOuter->Release();
    else return NondelegatingRelease();
    }
     
    HRESULT CA::QueryInterface(const IID& iid, void** ppv)
    {
    if(m_pUnknownOuter != NULL) return m_pUnknownOuter->QueryInterface(iid, ppv);
    else return NondelegatingQueryInterface(iid, ppv);
    }
     
    int CA::Somefunction()
    {
    printf("调用com对象A的接口!\n");
    return 1;
    }
     
    类厂:Factory.h
    #ifndef __Factory_H__
    #define __Factory_H__
     
     
    #include "Unknwn.h"
     
    class CAFactory : public IClassFactory
    {
    protected:
    ULONG m_Ref;
     
    public:
    CAFactory();
    ~CAFactory();
     
    HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
    ULONG __stdcall AddRef();
    ULONG __stdcall Release();
     
    HRESULT __stdcall CreateInstance(IUnknown*, const IID& iid, void** ppv);
    HRESULT __stdcall LockServer(BOOL);
    };
     
    #endif
     
    Factory.cpp
    #include "stdafx.h"
    #include "Factory.h"
    #include "4_A.h"
     
    extern ULONG g_LockNumber;
    extern ULONG g_4_ANumber;
     
    CAFactory::CAFactory()
    {
    m_Ref = 0;
    }
     
     
    CAFactory::~CAFactory()
    {
     
    }
     
     
    HRESULT CAFactory::QueryInterface(const IID& iid, void** ppv)
    {
    if(iid == IID_IUnknown)
    {
    *ppv = (IUnknown*) this;
    ((IUnknown*)(*ppv))->AddRef();
    }
    else if(iid == IID_IClassFactory)
    {
    *ppv = (IClassFactory*) this;
    ((IClassFactory*)(*ppv))->AddRef();
    }
    else
    {
    *ppv = NULL;
    return E_NOINTERFACE;
    }
     
    return S_OK;
    }
     
    ULONG CAFactory::AddRef()
    {
    m_Ref++;
    return (ULONG) m_Ref;
    }
     
    ULONG CAFactory::Release()
    {
    m_Ref--;
    if(m_Ref == 0)
    {
    delete this;
    return 0;
    }
     
    return (ULONG) m_Ref;
    }
     
    HRESULT CAFactory::CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv)
    {
    HRESULT hr;
     
    if((pUnknownOuter != NULL) && (iid != IID_IUnknown))
    {
    return CLASS_E_NOAGGREGATION;
    }
     
    *ppv = NULL;
    hr = E_OUTOFMEMORY;
     
    CA* pObj = new CA(pUnknownOuter);
    if(pObj == NULL) return hr;
     
    hr = pObj->NondelegatingQueryInterface(iid, ppv);
    if(hr != S_OK)
    {
    g_4_ANumber--;
    delete pObj;
    }
     
    return hr;
    }
     
    HRESULT CAFactory::LockServer(BOOL bLock)
    {
    if(bLock) g_LockNumber++;
    else g_LockNumber--;
     
    return NOERROR;
    }
     
    解释:这里定义了一个接口INondelegatingUnknown,这个接口和IUnknown接口是一级的,只是这里的分工不同,这里IUnknown接口用来聚合用,而INondelegatingUnknown则是接口本身应有的功能。IUnknown作为聚合用就是它的功能是调用了com对象B的接口基本功能。
     
    com对象B

     
    代码:
    接口:ISomeInterface.h
    #ifndef __SomeInterface_H__
    #define __SomeInterface_H__
     
    #include "Unknwn.h"
     
    extern "C" const GUID IID_SomeInterface;
     
    class ISomeInterface : public IUnknown
    {
    public:
    virtual int __stdcall Somefunction() = 0;
    };
     
    #endif
     
    IOtherInterface.h
    #ifndef __IOtherInterface_H__
    #define __IOtherInterface_H__
     
    #include "Unknwn.h"
     
    extern "C" const GUID IID_OtherInterface;
     
    class IOtherInterface : public IUnknown
    {
    public:
    virtual BOOL __stdcall Otherfunction() = 0;
    };
     
    #endif
     
    对象:4_B.h
    #ifndef __4_B_H__
    #define __4_B_H__
     
    #ifndef __SomeInterface_H__
    #include "SomeInterface.h"
    #endif
     
    #ifndef __OtherInterface_H__
    #include "OtherInterface.h"
    #endif
     
     
    class CB : public IOtherInterface
    {
    protected:
    ULONG m_Ref;
     
    public:
    CB();
    ~CB();
     
    HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
    ULONG __stdcall AddRef();
    ULONG __stdcall Release();
     
    BOOL __stdcall Otherfunction();
     
    HRESULT Init();
     
    private:
    IUnknown* m_pUnknownInner;
    ISomeInterface* m_pSomeInterface;
    };
     
    #endif
     
    4_B.cpp
    #include "stdafx.h"
    #include <comutil.h>
    #include <stdio.h>
    #include "objbase.h"
    #include "olectl.h"
     
    #include "4_B.h"
    #include "Factory.h"
    #include "Registry.h"
     
     
     
    ULONG g_LockNumber = 0;
    ULONG g_4_BNumber = 0;
    HANDLE g_hModule;
     
     
     
    extern "C" const GUID CLSID_4_A =
    { 0x753e2e9d, 0x7acf, 0x423f,
    { 0xae, 0x87, 0x71, 0xd, 0x88, 0xee, 0xfd, 0x42 } };
    extern "C" const GUID IID_SomeInterface =
    { 0x753e2e9e, 0x7acf, 0x423f,
    { 0xae, 0x87, 0x71, 0xd, 0x88, 0xee, 0xfd, 0x42 } };
     
    extern "C" const GUID CLSID_4_B =
    { 0x763e2e9d, 0x7acf, 0x423f,
    { 0xae, 0x87, 0x71, 0xd, 0x88, 0xee, 0xfd, 0x42 } };
    extern "C" const GUID IID_OtherInterface =
    { 0x763e2e9e, 0x7acf, 0x423f,
    { 0xae, 0x87, 0x71, 0xd, 0x88, 0xee, 0xfd, 0x42 } };
     
     
     
     
     
    BOOL APIENTRY DllMain( HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    g_hModule = hModule;
     
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }
     
     
     
    extern "C" HRESULT __stdcall DllGetClassObject(const CLSID& clsid, const IID& iid, void **ppv)
    {
    if (clsid == CLSID_4_B)
    {
     
    CBFactory *pFactory = new CBFactory;
     
    if (pFactory == NULL) return E_OUTOFMEMORY ;
     
    HRESULT result = pFactory->QueryInterface(iid, ppv);
     
    return result;
    }
    else return CLASS_E_CLASSNOTAVAILABLE;
    }
     
     
     
    extern "C" HRESULT __stdcall DllCanUnloadNow(void)
    {
    if ((g_4_BNumber == 0) && (g_LockNumber == 0)) return S_OK;
    else return S_FALSE;
    }
     
     
    extern "C" HRESULT __stdcall DllRegisterServer()
    {
    char szModule[1024];
    DWORD dwResult = ::GetModuleFileName((HMODULE)g_hModule, szModule, 1024);
    if (dwResult == 0) return SELFREG_E_CLASS;
    return RegisterServer(CLSID_4_B, szModule, "4_B.Object", "4_B Component", NULL);
    }
     
     
     
    extern "C" HRESULT __stdcall DllUnregisterServer()
    {
    return UnregisterServer(CLSID_4_B, "4_B.Object", NULL);
    }
     
     
    CB::CB()
    {
    m_Ref = 0;
    g_4_BNumber++;
    m_pUnknownInner = NULL;
    }
     
    CB::~CB()
    {
    m_Ref = 1;
     
    IUnknown* pUnknownOuter = this;
    pUnknownOuter->AddRef();
     
    if(m_pSomeInterface != NULL) m_pSomeInterface->Release();
     
    if(m_pUnknownInner != NULL) m_pUnknownInner->Release();
    }
     
     
    HRESULT CB::Init()
    {
    IUnknown* pUnknownOuter = (IUnknown*) this;
    HRESULT result = ::CoCreateInstance(CLSID_4_A, pUnknownOuter, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**) &m_pUnknownInner);
    if(FAILED(result)) return E_FAIL;
     
    result = m_pUnknownInner->QueryInterface(IID_SomeInterface, (void**) &m_pSomeInterface);
    if(FAILED(result))
    {
    m_pUnknownInner->Release();
    return E_FAIL;
    }
     
    pUnknownOuter->Release();
    return S_OK;
    }
     
    ULONG CB::AddRef()
    {
    m_Ref++;
    return (ULONG) m_Ref;
    }
     
    ULONG CB::Release()
    {
    m_Ref--;
    if(m_Ref == 0)
    {
    g_4_BNumber--;
    delete this;
    return 0;
    }
     
    return (ULONG) m_Ref;
    }
     
     
    HRESULT CB::QueryInterface(const IID& iid, void** ppv)
    {
    if(iid == IID_IUnknown)
    {
    *ppv = (IUnknown*) this;
    ((IUnknown*)(*ppv))->AddRef();
    }
    else if(iid == IID_OtherInterface)
    {
    *ppv = (IOtherInterface*) this;
    ((IOtherInterface*)(*ppv))->AddRef();
    }
    else if(iid == IID_SomeInterface)
    {
    return m_pUnknownInner->QueryInterface(iid, ppv);
    }
    else
    {
    *ppv = NULL;
    return E_NOINTERFACE;
    }
     
    return S_OK;
    }
     
    BOOL CB::Otherfunction()
    {
    printf("调用com对象B的接口\n");
    return true;
    }
     
    类厂:Factory.h
    #ifndef __Factory_H__
    #define __Factory_H__
     
    #include "Unknwn.h"
     
    class CBFactory : public IClassFactory
    {
    protected:
    ULONG m_Ref;
     
    public:
    CBFactory();
    ~CBFactory();
     
    HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
    ULONG __stdcall AddRef();
    ULONG __stdcall Release();
     
    HRESULT __stdcall CreateInstance(IUnknown*, const IID& iid, void** ppv);
    HRESULT __stdcall LockServer(BOOL);
    };
     
    #endif
     
    Factory.cpp
    #include "stdafx.h"
    #include "Factory.h"
    #include "4_B.h"
     
    extern ULONG g_LockNumber;
    extern ULONG g_4_BNumber;
     
    CBFactory::CBFactory()
    {
    m_Ref = 0;
    }
     
    CBFactory::~CBFactory()
    {
     
    }
     
    HRESULT CBFactory::QueryInterface(const IID& iid, void** ppv)
    {
    if(iid == IID_IUnknown)
    {
    *ppv = (IUnknown*) this;
    ((IUnknown*)(*ppv))->AddRef();
    }
    else if(iid == IID_IClassFactory)
    {
    *ppv = (IClassFactory*) this;
    ((IClassFactory*)(*ppv))->AddRef();
    }
    else
    {
    *ppv = NULL;
    return E_NOINTERFACE;
    }
     
    return S_OK;
    }
     
    ULONG CBFactory::AddRef()
    {
    m_Ref++;
    return (ULONG) m_Ref;
    }
     
    ULONG CBFactory::Release()
    {
    m_Ref--;
    if(m_Ref == 0)
    {
    delete this;
    return 0;
    }
     
    return (ULONG) m_Ref;
    }
     
     
    HRESULT CBFactory::CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv)
    {
    CB* pObj;
    HRESULT hr;
     
    *ppv = NULL;
    hr = E_OUTOFMEMORY;
     
    if(pUnknownOuter != NULL) return CLASS_E_NOAGGREGATION;
     
    pObj = new CB();
    if(pObj == NULL) return hr;
     
    pObj->AddRef();
    hr = pObj->Init();
    if(FAILED(hr))
    {
    g_4_BNumber--;
    delete pObj;
    return E_FAIL;
    }
     
    hr = pObj->QueryInterface(iid, ppv);
    pObj->Release();
     
    return hr;
    }
     
     
    HRESULT CBFactory::LockServer(BOOL bLock)
    {
    if(bLock) g_LockNumber++;
    else g_LockNumber--;
     
    return NOERROR;
    }
     
    解释:这里有个函数Init(),这个函数的作用就是调用对象A,获得A对象的接口指针,为后面调用做准备。
     
    调用程序:

     
    代码:
    call.cpp
     
    #include "windows.h"
    #include <stdio.h>
    #include <comutil.h>
    #include <conio.h>
     
    #include "SomeInterface.h"
    #include "OtherInterface.h"
     
     
    extern "C" const GUID IID_SomeInterface =
    { 0x753e2e9e, 0x7acf, 0x423f,
    { 0xae, 0x87, 0x71, 0xd, 0x88, 0xee, 0xfd, 0x42 } };
     
     
    extern "C" const GUID IID_OtherInterface =
    { 0x763e2e9e, 0x7acf, 0x423f,
    { 0xae, 0x87, 0x71, 0xd, 0x88, 0xee, 0xfd, 0x42 } };
     
    void main()
    {
    IUnknown* pUnknown;
    ISomeInterface* pSomeInterface;
    IOtherInterface* pOtherInterface;
    HRESULT hResult;
    GUID objectCLSID;
     
    if(CoInitialize(NULL) != S_OK)
    {
    printf("Initialize COM library failed!\n");
    return;
    }
     
    hResult = ::CLSIDFromProgID(L"4_B.Object", &objectCLSID);
    if(FAILED(hResult))
    {
    printf("Can't find the 4_B CLSID!\n");
    CoUninitialize();
    return;
    }
     
    hResult = CoCreateInstance(objectCLSID, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**) &pUnknown);
    if(FAILED(hResult))
    {
    printf("Create object failed!\n");
    CoUninitialize();
    return;
    }
     
    hResult = pUnknown->QueryInterface(IID_SomeInterface, (void**) &pSomeInterface);
    pUnknown->Release();
    if(FAILED(hResult))
    {
    printf("QueryInterface ISomeInterface failed!\n");
    CoUninitialize();
    return;
    }
    pSomeInterface->Somefunction();
     
    hResult = pSomeInterface->QueryInterface(IID_OtherInterface, (void**) &pOtherInterface);
    pSomeInterface->Release();
    if(FAILED(hResult))
    {
    printf("QueryInterface IOtherInterface failed!\n");
    CoUninitialize();
    return;
    }
    pOtherInterface->Otherfunction();
     
    pOtherInterface->Release();
    CoUninitialize();
     
    getch();
    return;
    }
     
    运行结果:

  • 相关阅读:
    kthread_run
    05 七段数码管的实现
    Docker 面临的安全隐患,我们该如何应对
    7 天玩转 ASP.NET MVC — 第 6 天
    哪些问题困扰着我们?DevOps 使用建议
    如何使用 OneAPM 监控微软 Azure Cloud Service ?
    在 Java 中如何更高效地存储和管理 SQL 语句?
    规模化敏捷开发的10个最佳实践(上)
    如何在 Swift 语言下使用 iOS Charts API 制作漂亮图表?
    PHP 性能分析与实验——性能的宏观分析
  • 原文地址:https://www.cnblogs.com/waterhsu/p/com_juhe.html
Copyright © 2020-2023  润新知