`

Brew中的Module的实现方法

    博客分类:
  • brew
阅读更多
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}
第4行申请AEEMod结构体类型的pMe指针,该结构体的定义如下:
01//Structure that implements the IModule interface
02
typedef 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;
所以DECLARE_VTBL(IModule)就是: IModule vtIModule;
IModule是一个结构体类型,定义如下:
1typedef struct _IModule         IModule;
所以,我们需要了解_IModule的结构体是什么样子的。我们需要从下面的四行代码入手,不过下面主要是两个宏定义,需要展开才能够明白它们到底是什么东西。
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*)
先将QINTERFACE(IModule)展开,根据上面第16到20行的定义以及第22行VTBL的定义,得到:
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);
将以上结果合并起来,就可以得到如下代码:
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
我们以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
分享到:
评论

相关推荐

    brew applet框架分析

    BREW Applet框架分析主要探讨了在BREW(Binary Runtime Environment for Wireless)平台上如何设计和实现Applet,以及如何在一个Module中实现多个Applet。BREW是由QUALCOMM公司开发的一种针对无线设备的应用程序开发...

    BREW Applet框架.doc

    **Module**是BREW系统中承载Applet和Extension的容器,它由MIF(Module Information File)文件描述其属性、包含的组件以及依赖关系。当BREW需要加载一个Applet或Extension时,首先会检查对应的Module是否已加载,若...

    开发BREW拓展类(extension)

    - 实现文件 (.cpp):实现接口中的方法。 - MIF文件 (.mif):描述Module的元数据信息。 2.3 Module Extension 关系 Extension与Applet一同存在于Module中,Extension的实例在需要时由Applet创建。 2.4 实现 ...

    BREW Applet框架

    BREW的应用程序实体主要由Applet和Extension组成,它们被组织在Module中。 1. **BREW概览** - **BREW简介**:BREW提供了一种跨平台的解决方案,允许开发者创建可运行在不同无线设备上的应用程序。它接受的软件实体...

    BREW详细介绍

    4. **面向设备制造商的BREW开放平台**:使设备制造商能够轻松地将BREW集成到他们的产品中,确保应用在不同硬件上的兼容性和性能。 #### 四、BREW 体系结构 BREW 的体系结构分为几个层次,包括: 1. **VM (Virtual...

    BREW SDK overview

    3. **应用模块层 (AppModule)**:用于实现BREW应用程序的核心功能。 4. **套接字层 (Sockets)**:支持网络通信。 5. **操作系统服务层 (OSServices)**:提供操作系统级别的服务。 6. **文件系统层 (FileSystem)**:...

    BREW开发商手册.doc

    - **高效性能**:优化了资源管理,使得在有限的设备资源下也能实现高效的应用运行。 - **广泛的兼容性**:支持多种设备和操作系统,提高了应用程序的市场覆盖率。 - **丰富的API**:涵盖了图形、网络、音频等多种...

    mac下使用brew配置环境的步骤分享

    在Mac操作系统中,Homebrew(简称brew)是一个非常流行的包管理器,用于简化软件的安装和管理过程。本文将详细讲解如何使用brew来配置开发环境,特别是针对PHP开发者,涉及Apache、Memcached以及PHP的扩展。 首先,...

    在Mac下彻底卸载node和npm的方法

    Node.js 的卸载方法可以使用以下命令实现: `uninstallNode.sh` 这个脚本将删除所有相关的文件和软连接。 卸载 Node.js 之后,需要重新安装相关的软件和命令行工具,以便继续使用它们。 Node.js 的卸载方法...

    goyaml:命令行实用程序,可对YAML文件执行简单的操作。 还包括转到类型YamlDoc和YamlFile,以快速,轻松地读写YAML文档的某些部分

    主要打算在shell脚本中使用。 获取来源 要获取该项目的源代码,请发出以下命令: $ GO111MODULE=on GOSUMDB=off go get github.com/theochva/goyaml 安装CLI 对于Mac OS,您可以通过自制软件安装命令: $ brew ...

    python3开发django项目安装和使用redis教程

    对于不同的操作系统,Redis 的安装方法有所不同: - **Linux**: - 使用包管理器安装,例如在 Ubuntu 上使用 `sudo apt-get install redis-server`。 - **Windows**: - Redis 官方提供了一个预编译的 Windows ...

    svn安装包(附权限管理,中文包,安装教程)

    - 使用 dav_svn_module 或者 authz_file 配置文件实现基于路径的权限控制,允许对仓库的不同部分设定不同权限。 4. SVN 中文包: - 对于中文环境,安装包含中文支持的 SVN 包可以让界面和帮助文档显示为中文,...

    xyzRecipes:简约的Web服务框架-实现食谱计划者生产力应用程序

    这可以通过bash中的brew install gradle命令来完成。 另外,大多数现代IDE的支持或与本机Gradle处理一起安装。 您可以使用git clone https://github.com/andewx/xyzRecipes克隆此项目然后在IDE中打开并导入根目录。...

    nginx所需要的依赖包

    通常,这些依赖包可以通过Linux发行版的包管理器(如apt-get for Debian/Ubuntu, yum for CentOS/RHEL, 或者brew for macOS)来获取和安装。例如,在Ubuntu上,你可以使用以下命令安装: ``` sudo apt-get update ...

    Torch for python on OSX

    在Torch中,我们可以使用`forward`方法进行前向传播,`backward`方法计算损失的梯度,然后使用优化器更新权重。以下是一个简单的训练循环: ```python for epoch in range(10): # 循环遍历数据集10次 for i, ...

Global site tag (gtag.js) - Google Analytics