[收录]基于COM思想实现AEEINTERFACE

来源:互联网 发布:sql语句多表查询count 编辑:程序博客网 时间:2024/06/05 02:15
基于COM思想实现AEEINTERFACE    作者: Qinix

    BREW平台上接口扩展一般都是以AEEINTERFACE的形式提供的,AEEINTERFACE封装类似于COM技术, 实现封装、继承和多态。当接口被定义和实现之后,可以用ISHELL_CreateInstance来创建接口实例。高通的AEEINTERFACE一般都是以C语言编写的,对于C++程序员来说,更喜欢用C++来实现。为了和更好的和大家进行探讨,本人写了一个用C++实现的AEEINTERFACE,作为素材与大家共享。由于本人实现的只是一种思想,具体实现与平台和编译器相关。

1. 首先实现一个COM接口ICat

1.1 IUnknown

   COM定义的每一个接口都必须从IUnknown继承,所以我们首先定义IUnknown接口。

   class IUnknown
   {
   public:
        virtual uint32 AddRef() = 0;                        //增加接口对象引用计数
            virtual uint32 Release() = 0;                        //减接口对象引用技术
            virtual int QueryInterface(AEECLSID cls, void** ppobj) = 0;        //查询相关接口
   };

    在该类中, AddRef(), Release(), QueryInterface()是一个COM接口必须具有的三个函数。同时COM是接口和实现相分离的,
所以都定义为虚函数。

    AEEINTERFACE接口对象也有这三个函数。

1.2 ICat接口

    ICat从IUnknown 接口派生。

    class ICat : public IUnknown
    {
    public:
            virtual void IgnoreMaster() = 0;
    };

1.3 CCat 类

    class CCat : public ICat
    {
    public:
            CCat();
            CCat(IShell* pIShell);
    
            //Override operator
            void* operator new(size_t  size);        //为Brew平台定制
            void operator delete(void* p);          //为Brew平台定制
    
            //IUnknown method    
            uint32 AddRef();
            uint32 Release();
            int QueryInterface(AEECLSID cls, void** ppobj);
    
            //ICat method
            void IgnoreMaster();
        
     protected:
            virtual ~CCat();
    
     private:
            uint32  m_uRef;
            IShell* m_pIShell; 
    };

        在类中将实现所有定义的函数。

1.4 创建COM接口实例的函数

    extern "C" int ICat_New(IShell* pIShell,AEECLSID cls,void** ppobj);

    COM实例的创建函数应该是编译器无关的,所以需要以C风格的函数提供该接口。

1.5 源文件

    int ICat_New(IShell* pIShell,AEECLSID cls,void** ppobj)
    {
            int nRet = SUCCESS;
            CCat* pCat = NULL;
    
            pCat = new CCat(pIShell);
            *ppobj = pCat;
                   
        return nRet;   
    }

    //Constructor
    CCat::CCat()
    {
    
    }

    CCat::CCat(IShell* pIShell)
    {
            m_pIShell = pIShell;
    }

    //Deconstuctor
    CCat::~CCat()
    {
        
    }

    void* CCat::operator new(size_t size)
    {
            void* pCat = (void*)MALLOC(size);

            return pCat;   
    }

    void CCat::operator delete(void* p)
    {
            if(p != NULL)
            {
              ((CCat*)p)->~CCat();
              FREEIF(p);
            }
    }

    //Add referece count
    uint32 CCat::AddRef()
    {
            return m_uRef++;
    }

    //Release
    uint32 CCat::Release()
    {
            if(m_uRef == 0)
          return 0;
        
            return m_uRef--;
    }

    //Query interface
    int CCat::QueryInterface(AEECLSID cls, void** ppobj)
    {
            ICat* pICat = NULL;
    
            if(cls == IID_CAT)
            {
                pICat = (ICat*)this;
                *ppobj = pICat;        
            }
    
            return SUCCESS;   
    }

    //IgnoreMaster
    void CCat::IgnoreMaster()
    {

    }
2. 实现AEETERFACE接口IICat

2.1 IICat头定义   

   typedef struct _IICat IICat;

   AEEINTERFACE(IICat)
   {
           INHERIT_IQueryInterface(IICat);
            void (*IgnoreMaster)(IICat* po);
   };

   #define IICAT_AddRef(p)                AEEGETPVTBL(p,IICat)->AddRef((p))
   #define IICAT_Release(p)                AEEGETPVTBL(p,IICat)->Release((p))
   #define IICAT_QueryInterface(p,i,o)         AEEGETPVTBL(p,IICat)->QueryInterface((p),(i),(o))                   
   #define IICAT_IgnoreMaster(p)                              AEEGETPVTBL(p,IICat)->IgnoreMaster((p))  

2.2 IICat源代码           

   将COM接口ICat作为IICat的成员, 这样就可以以C风格提供IICat接口。


   struct CICat
   {
            const AEEVTBL(IICat)       *pvt;
            uint32                      m_uRef;
            IShell                     *m_pIShell;   
            ICat*                       m_pCat;              
   };

   extern "C" int ICat_New(IShell* pIShell,AEECLSID cls,void** ppobj);

   extern "C" int IICat_New(IShell* pIShell,AEECLSID cls, void **ppo);
   static uint32      CICat_AddRef(IICat *po);
   static uint32      CICat_Release(IICat *po);
   static int         CICat_QueryInterface(IICat *po, AEECLSID id, void **ppo);
   static void        CICat_IgnoreMaster(IICat *po);

   static const IICatVtbl gvtIICat = {
                                CICat_AddRef,
                                CICat_Release,
                                CICat_QueryInterface
                        };

   int IICat_New(IShell* pIShell,AEECLSID cls, void **ppo)
   {
            int nReturn = ENOMEMORY;
            CICat *pme = NULL;

            pme = (CICat*)MALLOC(sizeof(CICat));
    
            ICat_New(pIShell, cls, (void**)&pme->m_pCat);

            if (pme) 
        {
            pme->pvt = &gvtIICat; 
            pme->m_uRef = 1;
            pme->m_pIShell = pIShell;
            nReturn = SUCCESS;
            }
           
        *ppo = pme;
            return nReturn;
    }

    static uint32 CICat_AddRef(IICat *po)
    {
            CICat* pme = (CICat*)po;
    
            return pme->m_pCat->AddRef();
    }

    static uint32 CICat_Release(IICat *po)
    {
            CICat* pme = (CICat*)po;

            return pme->m_pCat->Release();
    }

    static int CICat_QueryInterface(IICat *po, AEECLSID id, void **ppo)
    {
            CICat* pme = (CICat*)po;

            return pme->m_pCat->QueryInterface(id,ppo);
    }

    static void CICat_IgnoreMaster(IICat *po)
    {
            CICat* pme = (CICat*)po;

            return pme->m_pCat->IgnoreMaster(); 
    }                 

3. 结论

   通过上述封装后,可以提供IICat提供给C/C++程序员使用。他们不关心接口的实现,只关心接口的使用。

   EX:
   void TestIICat(CApp * pme)
   {
        IICat* pIICat;

        if(SUCCESS == ISHELL_CreateInstance(pme->a.m_pIShell, 
                                AEECLSID_IICAT,(void**)&pIICat)  
        {
             IICAT_IgnoreMaster(pIICat); 
             IICAT_Release(pIICat);
        }
   }