基于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);
}
}
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);
}
}