Brew中的Module的实现方法

8 views
Skip to first unread message

Chunlin Zhang

unread,
May 20, 2009, 2:18:47 AM5/20/09
to bre...@googlegroups.com
http://haorui215.javaeye.com/blog/385580

 
 

Sent to you by Chunlin Zhang via Google Reader:

 
 


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

已有 0 人发表留言,猛击->>这里<<-参与讨论


JavaEye推荐




 
 
 
 
Reply all
Reply to author
Forward
0 new messages