- 浏览: 198777 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
hao3721:
dsfasd
ehcache 使用 -
nihaokid:
方法是不会存在在对象内存中的,它存在于方法区,建议看看jvm的 ...
Java 深层理解 父类引用指向子类对象 -
vissalan:
有一点没看明白Father f1 = (Father)s;这时 ...
Java 深层理解 父类引用指向子类对象 -
咖啡舞者:
非常感谢这种分享精神.
在BREW中实现自己的GUI(8)-IWEB的封装 -
咖啡舞者:
这是创建的代码。
在设备上调的。
界面在手机和模拟器上显示的差异
Brew中的Module的实现方法:
【原创作者:shosh,http://www.yuleyx.com/shosh】
我们从AEEModGen.c中提供的用于创建Module对象的对外接口入手,函数如下:
01int AEEStaticMod_New(int16 nSize, IShell *pIShell, void *ph, IModule **ppMod,
02 PFNMODCreateINST pfnMC,PFNFREEMODDATA pfnMF)
03{
04 AEEMod *pMe = NULL;
05 VTBL(IModule) *modFuncs;
……………省略第6到73行的代码…………………
74}
01int AEEStaticMod_New(int16 nSize, IShell *pIShell, void *ph, IModule **ppMod,
02 PFNMODCreateINST pfnMC,PFNFREEMODDATA pfnMF)
03{
04 AEEMod *pMe = NULL;
05 VTBL(IModule) *modFuncs;
……………省略第6到73行的代码…………………
74}
第4行申请AEEMod结构体类型的pMe指针,该结构体的定义如下:
01//Structure that implements the IModule interface
02typedef struct _AEEMod
03{
04 DECLARE_VTBL(IModule) // Virtual Table with pointers to IModule functions
05
06 uint32 m_nRefs; // Reference count for this module
07 IShell * m_pIShell; // Pointer to IShell
08
09 //Address of CreateInstance function of the module. This is needed for
10 // static modules
11 PFNMODCreateINST pfnModCrInst;
12
13 //Address of the function to free the module data. This is needed for static
14 // modules that define their own data.
15 PFNFREEMODDATA pfnModFreeData;
16
17} AEEMod;
01//Structure that implements the IModule interface
02typedef struct _AEEMod
03{
04 DECLARE_VTBL(IModule) // Virtual Table with pointers to IModule functions
05
06 uint32 m_nRefs; // Reference count for this module
07 IShell * m_pIShell; // Pointer to IShell
08
09 //Address of CreateInstance function of the module. This is needed for
10 // static modules
11 PFNMODCreateINST pfnModCrInst;
12
13 //Address of the function to free the module data. This is needed for static
14 // modules that define their own data.
15 PFNFREEMODDATA pfnModFreeData;
16
17} AEEMod;
在该结构体的第4行,声明了一个Virtual Table(虚拟表:专门用来来存放函数指针的结构体,不过此处是指向该结构体的指针),这个是重点,待会将展开来讲。第6行的m_nRefs是模仿COM中的计数器,第11行和第15行的两个函数指针成员,其中pfnModCrInst是用来存放创建Module本身的函数(地址),而pfnModFreeData是Module自身提供释放自身数据的函数指针。
下面我们将结构体中的第四行DECLARE_VTBL(IModule)展开:
先来看看DECLARE_VTBL的定义:
1// Use as first member of classes that override QINTERFACE()
2#define DECLARE_VTBL(iname) iname vt##iname;
1// Use as first member of classes that override QINTERFACE()
2#define DECLARE_VTBL(iname) iname vt##iname;
所以DECLARE_VTBL(IModule)就是: IModule vtIModule;
IModule是一个结构体类型,定义如下:
1typedef struct _IModule IModule;
1typedef struct _IModule IModule;
所以,我们需要了解_IModule的结构体是什么样子的。我们需要从下面的四行代码入手,不过下面主要是两个宏定义,需要展开才能够明白它们到底是什么东西。
1QINTERFACE(IModule)
2{
3 INHERIT_IModule(IModule);
4};
1QINTERFACE(IModule)
2{
3 INHERIT_IModule(IModule);
4};
下面是所有相关的宏定义,先贴出来,然后再用这些定义将上面的4行慢慢展开:
01typedef struct _IModule IModule;
02#define INHERIT_IModule(iname) \
03 INHERIT_IBase(iname); \
04 int (*CreateInstance)(iname * po,IShell * pIShell,AEECLSID ClsId,void ** ppObj); \
05 void (*FreeResources)(iname * po, IHeap * ph, IFileMgr * pfm)
06
07QINTERFACE(IModule)
08{
09 INHERIT_IModule(IModule);
10};
11#define IMODULE_AddRef(p) GET_PVTBL(p,IModule)->AddRef(p)
12#define IMODULE_Release(p) GET_PVTBL(p,IModule)->Release(p)
13#define IMODULE_CreateInstance(p,ps,id,ppo) GET_PVTBL(p,IModule)->CreateInstance(p,ps,id,ppo)
14#define IMODULE_FreeResources(p,ph,pfm) GET_PVTBL(p,IModule)->FreeResources(p,ph,pfm)
15
16#define QINTERFACE(iname) struct _##iname {\
17 struct VTBL(iname) *pvt;\
18 };\
19 typedef struct VTBL(iname) VTBL(iname);\
20 struct VTBL(iname)
21
22#define VTBL(iname) iname##Vtbl
23
24#define INHERIT_IBase(iname) \
25 uint32 (*AddRef) (iname*);\
26 uint32 (*Release) (iname*)
01typedef struct _IModule IModule;
02#define INHERIT_IModule(iname) \
03 INHERIT_IBase(iname); \
04 int (*CreateInstance)(iname * po,IShell * pIShell,AEECLSID ClsId,void ** ppObj); \
05 void (*FreeResources)(iname * po, IHeap * ph, IFileMgr * pfm)
06
07QINTERFACE(IModule)
08{
09 INHERIT_IModule(IModule);
10};
11#define IMODULE_AddRef(p) GET_PVTBL(p,IModule)->AddRef(p)
12#define IMODULE_Release(p) GET_PVTBL(p,IModule)->Release(p)
13#define IMODULE_CreateInstance(p,ps,id,ppo) GET_PVTBL(p,IModule)->CreateInstance(p,ps,id,ppo)
14#define IMODULE_FreeResources(p,ph,pfm) GET_PVTBL(p,IModule)->FreeResources(p,ph,pfm)
15
16#define QINTERFACE(iname) struct _##iname {\
17 struct VTBL(iname) *pvt;\
18 };\
19 typedef struct VTBL(iname) VTBL(iname);\
20 struct VTBL(iname)
21
22#define VTBL(iname) iname##Vtbl
23
24#define INHERIT_IBase(iname) \
25 uint32 (*AddRef) (iname*);\
26 uint32 (*Release) (iname*)
先将QINTERFACE(IModule)展开,根据上面第16到20行的定义以及第22行VTBL的定义,得到:
1struct _IModule {
2 struct IModuleVtbl *pvt;
3 };
4 typedef struct IModuleVtbl IModuleVtbl;
5 struct IModuleVtbl
1struct _IModule {
2 struct IModuleVtbl *pvt;
3 };
4 typedef struct IModuleVtbl IModuleVtbl;
5 struct IModuleVtbl
再将INHERIT_IModule(IModule);展开,根据上面第2到5行的定义以及第24到26行INHERIT_IBase的定义,得到:
1 uint32 (*AddRef) (IModule*);
2 uint32 (*Release) (IModule*);
3 int (*CreateInstance)(IModule * po,IShell * pIShell,AEECLSID ClsId,void ** ppObj);
4 void (*FreeResources)(IModule * po, IHeap * ph, IFileMgr * pfm);
1 uint32 (*AddRef) (IModule*);
2 uint32 (*Release) (IModule*);
3 int (*CreateInstance)(IModule * po,IShell * pIShell,AEECLSID ClsId,void ** ppObj);
4 void (*FreeResources)(IModule * po, IHeap * ph, IFileMgr * pfm);
将以上结果合并起来,就可以得到如下代码:
01struct _IModule
02{
03 struct IModuleVtbl *pvt;
04};
05typedef struct IModuleVtbl IModuleVtbl;
06struct IModuleVtbl
07{
08 uint32 (*AddRef) (IModule*);
09 uint32 (*Release) (IModule*);
10 int (*CreateInstance)(IModule * po,IShell * pIShell,AEECLSID ClsId,void ** ppObj);
11 void (*FreeResources)(IModule * po, IHeap * ph, IFileMgr * pfm);
12};
01struct _IModule
02{
03 struct IModuleVtbl *pvt;
04};
05typedef struct IModuleVtbl IModuleVtbl;
06struct IModuleVtbl
07{
08 uint32 (*AddRef) (IModule*);
09 uint32 (*Release) (IModule*);
10 int (*CreateInstance)(IModule * po,IShell * pIShell,AEECLSID ClsId,void ** ppObj);
11 void (*FreeResources)(IModule * po, IHeap * ph, IFileMgr * pfm);
12};
好,现在来总结一下:
前面已经说到DECLARE_VTBL(IModule)就是: IModule vtIModule;,它作为AEEMod结构体的第一个成员。IModule是_IModule的结构体类型,_IModule结构体只有一个成员,就是结构体IModuleVtbl的指针。而IModuleVtbl指向的是虚拟函数表的首地址,所以如果有一个IModule* p的指针,p->pvt就是IModuleVtbl*的类型,再用p->pvt->functionName找到对应的函数。为了方便,虚拟函数表中函数的调用是使用宏来定义的,从结构体IModuleVtbl中我们可以看到Module提供了四种方法,宏定义如下,其中还用到GET_PVTBL宏定义:
1#define IMODULE_AddRef(p) GET_PVTBL(p,IModule)->AddRef(p)
2#define IMODULE_Release(p) GET_PVTBL(p,IModule)->Release(p)
3#define IMODULE_CreateInstance(p,ps,id,ppo) GET_PVTBL(p,IModule)->CreateInstance(p,ps,id,ppo)
4#define IMODULE_FreeResources(p,ph,pfm) GET_PVTBL(p,IModule)->FreeResources(p,ph,pfm)
5#define GET_PVTBL(p,iname) ((iname*)p)->pvt
1#define IMODULE_AddRef(p) GET_PVTBL(p,IModule)->AddRef(p)
2#define IMODULE_Release(p) GET_PVTBL(p,IModule)->Release(p)
3#define IMODULE_CreateInstance(p,ps,id,ppo) GET_PVTBL(p,IModule)->CreateInstance(p,ps,id,ppo)
4#define IMODULE_FreeResources(p,ph,pfm) GET_PVTBL(p,IModule)->FreeResources(p,ph,pfm)
5#define GET_PVTBL(p,iname) ((iname*)p)->pvt
我们以AddRef函数为例,我们调用的时候会使用"IMODULE_AddRef(p);"语句,将其展开,其实就是:
((IModule*)p)->pvt->AddRef(p);
这样就实现了虚拟函数表中函数的调用了。
下面再回到用于创建Module对象的对外接口AEEStaticMod_New,具体代码如下:
01int AEEStaticMod_New(int16 nSize, IShell *pIShell, void *ph, IModule **ppMod,
02 PFNMODCreateINST pfnMC,PFNFREEMODDATA pfnMF)
03{
04 AEEMod *pMe = NULL;
05 VTBL(IModule) *modFuncs; //将其展开就是 IModuleVtbl *modFuncs;
06
07 if (!ppMod || !pIShell) {
08 return EFAILED;
09 }
10
11 if (nSize < 0) {
12 return EBADPARM;
13 }
14 *ppMod = NULL;
15
16#ifdef AEE_SIMULATOR
17 // IMPORTANT NOTE: g_pvtAEEStdLibEntry global variable is defined for
18 // SDK ONLY! This variable should NOT BE:
19 //
20 // (1) overwritten
21 // (2) USED DIRECTLY by BREW SDK users.
22 //
23 // g_pvtAEEStdLibEntry is used as an entry point to AEEStdLib,
24 // DO NOT REMOVE the next five lines.
25 if (!ph) {
26 return EFAILED;
27 } else {
28 g_pvtAEEStdLibEntry = (AEEHelperFuncs *)ph;
29 }
30#endif
31
32 //Allocate memory for the AEEMod object
33
34 if (nSize < sizeof(AEEMod)) {
35 nSize += sizeof(AEEMod);
36 }
37
38 if (NULL == (pMe = (AEEMod *)MALLOC(nSize + sizeof(IModuleVtbl)))) {
39 return ENOMEMORY;
40 }
41
42 // Allocate the vtbl and initialize it. Note that the modules and apps
43 // must not have any static data. Hence, we need to allocate the vtbl as
44 // well.
45
46 modFuncs = (IModuleVtbl *)((byte *)pMe + nSize);
47
48 // Initialize individual entries in the VTBL
49 modFuncs->AddRef = AEEMod_AddRef;
50 modFuncs->Release = AEEMod_Release;
51 modFuncs->CreateInstance = AEEMod_CreateInstance;
52 modFuncs->FreeResources = AEEMod_FreeResources;
53
54
55 // initialize the vtable
56 INIT_VTBL(pMe, IModule, *modFunc
02 PFNMODCreateINST pfnMC,PFNFREEMODDATA pfnMF)
03{
04 AEEMod *pMe = NULL;
05 VTBL(IModule) *modFuncs; //将其展开就是 IModuleVtbl *modFuncs;
06
07 if (!ppMod || !pIShell) {
08 return EFAILED;
09 }
10
11 if (nSize < 0) {
12 return EBADPARM;
13 }
14 *ppMod = NULL;
15
16#ifdef AEE_SIMULATOR
17 // IMPORTANT NOTE: g_pvtAEEStdLibEntry global variable is defined for
18 // SDK ONLY! This variable should NOT BE:
19 //
20 // (1) overwritten
21 // (2) USED DIRECTLY by BREW SDK users.
22 //
23 // g_pvtAEEStdLibEntry is used as an entry point to AEEStdLib,
24 // DO NOT REMOVE the next five lines.
25 if (!ph) {
26 return EFAILED;
27 } else {
28 g_pvtAEEStdLibEntry = (AEEHelperFuncs *)ph;
29 }
30#endif
31
32 //Allocate memory for the AEEMod object
33
34 if (nSize < sizeof(AEEMod)) {
35 nSize += sizeof(AEEMod);
36 }
37
38 if (NULL == (pMe = (AEEMod *)MALLOC(nSize + sizeof(IModuleVtbl)))) {
39 return ENOMEMORY;
40 }
41
42 // Allocate the vtbl and initialize it. Note that the modules and apps
43 // must not have any static data. Hence, we need to allocate the vtbl as
44 // well.
45
46 modFuncs = (IModuleVtbl *)((byte *)pMe + nSize);
47
48 // Initialize individual entries in the VTBL
49 modFuncs->AddRef = AEEMod_AddRef;
50 modFuncs->Release = AEEMod_Release;
51 modFuncs->CreateInstance = AEEMod_CreateInstance;
52 modFuncs->FreeResources = AEEMod_FreeResources;
53
54
55 // initialize the vtable
56 INIT_VTBL(pMe, IModule, *modFunc
发表评论
-
手机开发平台指南、教程和资料介绍(转载)
2009-05-13 15:58 2614欢迎转载,转载请注明出处。作者:手机即信息 博客:http:/ ... -
Brew常见错误整理
2009-05-07 16:26 12811.用户是否可以将信息上传到开发商的服务器上来?用户传上来 ... -
BREW-教你设计用户界面
2009-04-24 16:14 1988这个书高通下的pdf, ... -
AppLoader的使用
2009-04-24 16:12 2687AppLoader是Brew Tools Suite3.0. ... -
程序在模拟器中的调试
2009-04-24 16:11 1241通过高通的FAQ知道:DBGPRINTF可以在vc的调试窗口和 ... -
程序在手机上的调试
2009-04-24 16:11 1098仍然通过高通的FAQ知道:DBGPRINTF的内容,当 ... -
浅谈ISocket的使用
2009-04-24 16:10 1813环境:brew sdk3.0中文版 + vc6.0 ... -
WEBOPT中http代理的设置
2009-04-24 16:09 1205原代码如下: awo[i].nId = WEBOPT_ ... -
强大的IWEB接口
2009-04-24 16:08 2122概述 本文着重介绍了在1.1SDK中引入的IWEB接口,以及 ... -
关于音频的播放
2009-04-24 16:06 1476先了解一下brew中可以 ... -
关于文件的读写
2009-04-24 16:05 2276brew中对文件操作需要 ... -
界面在手机和模拟器上显示的差异
2009-04-24 16:04 1753高通告诫我们:程序一定要多多在手机上调试。 刚入门时 ... -
在BREW中实现自己的GUI(8)-IWEB的封装
2009-04-13 17:43 2050封装IWeb其实并不算是GUI的范畴,但是一并说了罢。在BRE ... -
在BREW中实现自己的GUI(7)-动态效果的实现
2009-04-13 17:41 1773今天讨论关于GUI的另一个话题:如何在两个界面切换中表现出比较 ... -
在BREW中实现自己的GUI(6)-单选框与复选框的实现
2009-04-13 17:40 1564还有一个常用的UI控件是单选框与复选框。可惜BREW也不提供, ... -
在BREW中实现自己的GUI(5)-滚动条的实现
2009-04-13 17:38 1290前面做IGStatic时我们用到了一个滚动条组件IGScrol ... -
在BREW中实现自己的GUI(4)-IGStatic的实现
2009-04-13 17:37 1609BREW中的IStatic可以方便地显示一个文本,但是它没有背 ... -
在BREW中实现自己的GUI(3)-做一个跑马灯的效果
2009-04-13 17:37 1679有时如果我们在应用中需要提供一个滚动的信息提示条(类似于页面上 ... -
在BREW中实现自己的GUI(2)-TabPane的实现
2009-04-13 17:35 1293同样是定义一下几个实体结构: //自定义菜单项type ... -
在BREW中实现自己的GUI(1)-图形化菜单的实现
2009-04-13 17:34 2233要实现的菜单比较简单,只支持列表视图,也就是IMenuCtl中 ...
相关推荐
BREW Applet框架分析主要探讨了在BREW(Binary Runtime Environment for Wireless)平台上如何设计和实现Applet,以及如何在一个Module中实现多个Applet。BREW是由QUALCOMM公司开发的一种针对无线设备的应用程序开发...
**Module**是BREW系统中承载Applet和Extension的容器,它由MIF(Module Information File)文件描述其属性、包含的组件以及依赖关系。当BREW需要加载一个Applet或Extension时,首先会检查对应的Module是否已加载,若...
- 实现文件 (.cpp):实现接口中的方法。 - MIF文件 (.mif):描述Module的元数据信息。 2.3 Module Extension 关系 Extension与Applet一同存在于Module中,Extension的实例在需要时由Applet创建。 2.4 实现 ...
BREW的应用程序实体主要由Applet和Extension组成,它们被组织在Module中。 1. **BREW概览** - **BREW简介**:BREW提供了一种跨平台的解决方案,允许开发者创建可运行在不同无线设备上的应用程序。它接受的软件实体...
4. **面向设备制造商的BREW开放平台**:使设备制造商能够轻松地将BREW集成到他们的产品中,确保应用在不同硬件上的兼容性和性能。 #### 四、BREW 体系结构 BREW 的体系结构分为几个层次,包括: 1. **VM (Virtual...
3. **应用模块层 (AppModule)**:用于实现BREW应用程序的核心功能。 4. **套接字层 (Sockets)**:支持网络通信。 5. **操作系统服务层 (OSServices)**:提供操作系统级别的服务。 6. **文件系统层 (FileSystem)**:...
- **高效性能**:优化了资源管理,使得在有限的设备资源下也能实现高效的应用运行。 - **广泛的兼容性**:支持多种设备和操作系统,提高了应用程序的市场覆盖率。 - **丰富的API**:涵盖了图形、网络、音频等多种...
在Mac操作系统中,Homebrew(简称brew)是一个非常流行的包管理器,用于简化软件的安装和管理过程。本文将详细讲解如何使用brew来配置开发环境,特别是针对PHP开发者,涉及Apache、Memcached以及PHP的扩展。 首先,...
Node.js 的卸载方法可以使用以下命令实现: `uninstallNode.sh` 这个脚本将删除所有相关的文件和软连接。 卸载 Node.js 之后,需要重新安装相关的软件和命令行工具,以便继续使用它们。 Node.js 的卸载方法...
主要打算在shell脚本中使用。 获取来源 要获取该项目的源代码,请发出以下命令: $ GO111MODULE=on GOSUMDB=off go get github.com/theochva/goyaml 安装CLI 对于Mac OS,您可以通过自制软件安装命令: $ brew ...
对于不同的操作系统,Redis 的安装方法有所不同: - **Linux**: - 使用包管理器安装,例如在 Ubuntu 上使用 `sudo apt-get install redis-server`。 - **Windows**: - Redis 官方提供了一个预编译的 Windows ...
- 使用 dav_svn_module 或者 authz_file 配置文件实现基于路径的权限控制,允许对仓库的不同部分设定不同权限。 4. SVN 中文包: - 对于中文环境,安装包含中文支持的 SVN 包可以让界面和帮助文档显示为中文,...
这可以通过bash中的brew install gradle命令来完成。 另外,大多数现代IDE的支持或与本机Gradle处理一起安装。 您可以使用git clone https://github.com/andewx/xyzRecipes克隆此项目然后在IDE中打开并导入根目录。...
通常,这些依赖包可以通过Linux发行版的包管理器(如apt-get for Debian/Ubuntu, yum for CentOS/RHEL, 或者brew for macOS)来获取和安装。例如,在Ubuntu上,你可以使用以下命令安装: ``` sudo apt-get update ...
在Torch中,我们可以使用`forward`方法进行前向传播,`backward`方法计算损失的梯度,然后使用优化器更新权重。以下是一个简单的训练循环: ```python for epoch in range(10): # 循环遍历数据集10次 for i, ...