在第一次接触brew时,我就在疑问:“brew中的接口是个什么概念啊!”,而且发现它里面就没有数据,只有一个指针。后来慢慢才熟悉和明白了brew的接口的实质和内存布局。
如果你要揪跟问底,那你可以跟踪到其定义的头文件中看看究竟。那我就以IFileMgr为例子来看看究竟!(别的都类似)
当我跟踪进去后,我发现头文件
#defineVTBL(iname)iname##Vtbl
#defineQINTERFACE(iname)
struct_##iname{
structVTBL(iname)*pvt;
};
typedefstructVTBL(iname)VTBL(iname);
structVTBL(iname)
#defineINHERIT_IFileMgr(iname)
INHERIT_IBase(iname);
IFile*(*OpenFile)(iname*piname,constchar*pszFile,OpenFileModemode);
int(*GetInfo)(iname*piname,constchar*pszName,FileInfo*pInfo);
int(*Remove)(iname*piname,constchar*pszName);
int(*MkDir)(iname*piname,constchar*pszDir);
int(*RmDir)(iname*piname,constchar*pszDir);
int(*Test)(iname*piname,constchar*pszName);
uint32(*GetFreeSpace)(iname*piname,uint32*pdwTotal);
int(*GetLastError)(iname*piname);
int(*EnumInit)(iname*piname,constchar*pszDir,booleanbDirs);
boolean(*EnumNext)(iname*piname,FileInfo*pInfo);
int(*Rename)(iname*pfm,constchar*pszSrc,constchar*pszDest);
boolean(*EnumNextEx)(iname*pfm,AEEFileInfoEx*pInfo);
int(*SetDescription)(iname*pfm,constchar*pszName,AECHAR*pszDesc);
int(*GetInfoEx)(iname*pfm,constchar*pszName,AEEFileInfoEx*pi);
int(*Use)(iname*pfm,constchar*pszName,booleanbUse);
int(*GetFileUseInfo)(IFileMgr*pfm,AEEFileUseInfo*pfu)
QINTERFACE(IFileMgr)
{
INHERIT_IFileMgr(IFileMgr);
};
中都是一些宏定义,主要就是QINTERFACE(IFileMgr)
宏,我将其一层层展开:
struct_IFileMgr{
structIFileMgr_Vtbl*pvt;
};
typedefstructIFileMgr_VtblIFileMgr_Vtbl;
structIFileMgr_Vtbl
{
INHERIT_IBase(IFileMgr);
IFile*(*OpenFile)(IFileMgr*piname,constchar*pszFile,OpenFileModemode);
int(*GetInfo)(IFileMgr*piname,constchar*pszName,FileInfo*pInfo);
int(*Remove)(IFileMgr*piname,constchar*pszName);
int(*MkDir)(IFileMgr*piname,constchar*pszDir);
int(*RmDir)(IFileMgr*piname,constchar*pszDir);
int(*Test)(IFileMgr*piname,constchar*pszName);
uint32(*GetFreeSpace)(IFileMgr*piname,uint32*pdwTotal);
int(*GetLastError)(IFileMgr*piname);
int(*EnumInit)(IFileMgr*piname,constchar*pszDir,booleanbDirs);
boolean(*EnumNext)(IFileMgr*piname,FileInfo*pInfo);
int(*Rename)(IFileMgr*pfm,constchar*pszSrc,constchar*pszDest);
boolean(*EnumNextEx)(IFileMgr*pfm,AEEFileInfoEx*pInfo);
int(*SetDescription)(IFileMgr*pfm,constchar*pszName,AECHAR*pszDesc);
int(*GetInfoEx)(IFileMgr*pfm,constchar*pszName,AEEFileInfoEx*pi);
int(*Use)(IFileMgr*pfm,constchar*pszName,booleanbUse);
int(*GetFileUseInfo)(IFileMgr*pfm,AEEFileUseInfo*pfu)
}
typedefstruct_IFileMgrIFileMgr
原来就是个IFileMgr就是个结构体,结构体中只有一项就是另一个结构体的指针,现在突然明白了,为什么原来sizeof(IFileMgr)
= 4呢?那么这个指针指向的结构体是什么东西啊,看看里面的定义都是一些函数指针,仔细分析会发现所有的函数指针都是这个接口提供的函数!
第一项是个宏:INHERIT_IBase(IFileMgr);
我不想多说了,这个其实就是IBase接口提供的引用记数功能,每个接口的第一项就是它。
现在有个疑问了,那么这个接口的数据在那里放着呢?废话啊,不在头文件中就在实现文件中。对,这点不容质疑。但是究竟这个数据是怎么和函数联系起来的呢?那我就要猜测了!(不猜测也不行,因为实现文件编译成二进制了)。高通对知识产权保护的真是到位啊(这是他一贯的作风)!怎么猜测呢?
我先看看怎么使用一个接口。大部分接口都是通过ISHELL_CreateInstance(IShell * pIShell, AEECLSID cls,
void** ppobj ) 创建的。然后就使用这个创建的pobj调用函数如OpenFile(IFileMgr * piname, const char
*pszFile, OpenFileMode
mode)。每个函数的第一个参数就是接口指针。正如前面分析的宏,这个函数也是个宏定义,变成调用虚表中相应的函数指针指向的函数。指向的函数就是真真正正实现的函数。
那么现在考虑2个问题:
1. 在写这些函数时如何得到数据的存储地址,你只是有一个虚表的地址,那我想这些
数据应该是紧放在虚表后面的空间中连续存放,否则函数无法得到数据。
2.函数指针应该初始化,以指向真实的实现函数,而且还要为数据和虚表分配空间。
我们可以肯定第1个问题是正确的。那么2个问题在那里做这些工作呢?我猜测的是ISHELL_CreateInstance中,因为ISHELL_CreateInstance返回时,接口已经建立好了,可以调用接口的函数了!如果不在ISHELL_CreateInstance中,那恐怕函数都调用不了啊!!
我尝试写了一个大概示意代码:
/**/////////////////////////////////////////实现文件
/**///////////////////////////////////////
//接口数据定义
typedefstruct_IFileMgr_Data
{
charfileName[30];
intfile_pos;
}IFileMgr_Data;
//根据不同的AEECLSID调用具体接口的初始化函数
ISHELL_CreateInstance(IShell*pIShell,AEECLSIDcls,void**ppobj)
{
switch(cls)
{
caseAEECLSID_FILEMGR:
AllocFileMgr(ppobj);
}
}
intAllocFileMgr(IFileMgr**ppobj)
{
if(!ppobj)
return(FALSE);
*ppobj=NULL;
//分配内存
*ppobj=(IFileMgr*)malloc(sizof(IFileMgr)+sizeof(IFileMgr_Data));
//初始化虚表
(*ppobj)->pvt=(IFileMgr_Vtbl*)malloc(sizeof(IFileMgr_Vtbl));
//下面的open_fileandget_info是我假设的真实实现函数
(*ppobj)->pvt->OpenFile=open_file;
(*ppobj)->pvt->GetInfo=get_info;
//初始化数据
(IFileMgr_Data*)(*ppobj+sizof(IFileMgr))->file_pos=0;
}
如果你看懂上面的函数,说明你理解了接口了吧!
分享到:
相关推荐
BREW 常用接口介绍BREW 常用接口介绍BREW 常用接口介绍
BREW接口的继承和多态.pdf 一篇深入理解brew接口关联关系的文档 对于c语言的学习人员也非常有用
文档目的:由于几乎没有详细阐述 文档目的:由于几乎没有详细阐述BREW BREW接口实现机制方 接口实现机制方 面的文档,妨害了对 面的文档,妨害了对BREW BREW接口机制的学习。所以结合自 接口机制的学习。所以结合...
brew 多媒体接口,imedia接口,imediavideo接口
BREW开发培训系列——高级——BREW 常用接口介绍
很好的brew内存泄漏的说明,大家可以参考一下。
BREW开发培训系列——高级——BREW多媒体接口
第3章 BREW多媒体接口 第4章 IVocoder接口介绍 第5章 ICamera接口 第6章 BREW 常用接口介绍 第7章 BREW 3.1 文件系统 第8章 BREW 3.1 SMS新接口使用方法 第9章 BREW 语音呼叫业务 第10章 BREW 3.1.5 SP01 触摸屏...
说明brew接口实现原理,和c++面向对象对比。
详细的描述了BREW开发细节,BREW各个接口,并通过代码详细解释
第3章BREW多媒体接口 第4章IVocoder接口 第5章ICamera接口 第6章常用接口介绍 第7章BREW 3.1 文件系统 第8章BREW 3.1 SMS新接口使用方法 第9章BREW 语音呼叫业务 第10章BREW 3.1.5 SP01 触摸屏功能使用 第11章...
BREW手机游戏的内存管理
详细介绍BREW开发的高级技巧,以及接口
用C实现接口的例子,依照高通的brew编写,VC工程下通过编译,但是GCC下不行
一个在模拟器上定位BREW应用程序内存泄露位置的工具,可以给出内存泄露位置的调用栈信息(包括MALLOC、REALLOC分配的内存,也能定位到调用ISHELL_CreateInstance的位置)
高通Brew平台ICamera接口相关资料
Brew平台多媒体,以及MDP方面的文档
Brew 指南Brew 指南Brew 指南Brew 指南Brew 指南Brew 指南
基于BREW的铃音管理接口,帮助初学者参考
文件夹说明: Test1 : 第二章 软件基础 指针测试 Test2 : 第二章 软件基础 理解指针的本质 Test2-1 : 第二章 软件基础 指针的增减 Test3 : 第二章 软件... Test11 : 第十六章 扩展BREW接口 C++语言方式