开发 BREW Extension - 田海立的专栏 - CSDN博客

12 views
Skip to first unread message

Chunlin Zhang

unread,
May 26, 2009, 3:47:58 AM5/26/09
to BREW 中国开发者讨论组
http://blog.csdn.net/thl789/archive/2006/05/08/713323.aspx

 
 

Sent to you by Chunlin Zhang via Google Reader:

 
 

via blog.csdn.net on 5/26/09

开发 BREW Extension

Developing the BREW Extension

 

田海立

2006-5-7

 

摘要

从 BREW 应用开发者的角度,探讨 Extension 的实现。

 

 

摘要... 1

1 BREW概览... 1

1.1 BREW简介... 1

1.2 BREW中的几个基本概念... 2

1.3 BREW模拟开发环境... 2

2 开发BREW Extension. 3

2.1 Extension的应用场景... 3

2.2 文件组成... 4

2.3 Module Extension 中的关系... 5

2.4 实现Extension. 6

2.4.1 类型定义... 6

2.4.2 AEEClsCreateInstance() 的实现... 7

2.4.3 构造函数的实现... 8

3.2.4 SampleExt 对IBase 中方法的实现... 9

3.2.5 JustSayHello() 方法的实现... 10

3.2.6 ClinetApp 事件处理... 10

2.5 执行序列... 11

总结... 13

参考资料及进一步参考... 13

关于作者... 13

 

 

1 BREW概览

1.1 BREW简介

BREW(Binary Runtime Environment for Wireless,即无线二进制运行环境)是QUALCOMM 公司的产品。它以组件(COM)的组织形式封装了底层平台提供给应用开发的服务,屏蔽了底层的实现细节,而提供给应用层统一的API。它所提供的API描述的是Spec而非实现细节,不管今后QUALCOMM的平台技术如何发展,其实现的功能和实现该功能的API规范应该是确定并向后兼容的。

BREW上接受的OEM或其他第三方软件厂商提供的最终软件实体是Module的执行体——Win32模拟环境下是 *.dll,真实机器上是 *.mod,这也体现了BREW中的Binary。另外,也可以在BREW运行时从网络上下载BREW所接受的实体,加入到BREW中来运行。

1.2 BREW中的几个基本概念

BREW中的有Applet和Extension,Applet是一个独立运行(从应用开发角度看)的实体,有Applet Context,简记为ACONTEXT;Extension通过实现它所定义的接口提供服务给Applet或其它Extension,Extension不是独立的运行实体,它运行在调用它的Applet(直接或间接地,当前Extension Ext1的某个服务Ext1::srv可能不是由Applet直接调用,但是调用Ext1::srv的Extension Ext2归根到底还是可以追溯到某个Applet)的ACONTEXT中。Applet和Extension都是被包含在Module里面的,它们之间的关系如图一所示。

 

 

图一、BREW中几个概念之间的关系

 

       BREW最终接受的是Module,所以你所提供的Applet和Extension必须在某个Module中;另一方面,一个Module里可以有0…n个Applet或Extension,也可以同时有Applet和Extension,还可以两者都没有,不过两者都没有的Module也没有实际意义。Module的属性和它所包含的Applet和Extension的信息,以及Dependency关系都描述在MIF(Module Information File)文件里,BREW通过该描述文件检索它所需要的信息,并通过相应的Module二进制文件完成相应的操作。

       BREW加载Applet或Extension时,首先检查包含它的Module是否已经被加载到内存里,如果还没在内存里,BREW要做的工作是先把该Module加载;接着BREW通过该Module的IMODULE_CreateInstance() 来创建Applet或Extension的一个实例,然后才完成Applet或Extension的真正加载。

1.3 BREW模拟开发环境

本文所描述的BREW环境和概念都是基于BREW 3.0.1,采用的程序在下面软件环境中调试通过:

BREW SDK 3.0.1,包含
              API手册
              BREW Simulator, MIF Editor, etc.
              Header files & some src files

Microsoft Visual studio,包含
              Visual studio 6.0
              Visual studio 6.0 Service Package 5

       Additions
              BREW Application Wizard
              BREW Addins for vs60

 

2 开发BREW Extension

有了上面BREW的概念以及开发调试所需的软件环境,下面我们看如何实现一个BREW Extension。

BREW中的Extension虽然与Applet是两个概念,但是实现起来却基本相同,不同之处只是在于,Applet必须实现事件处理,而Extension没有这个要求。

 

2.1 Extension的应用场景

假定下面场景:一个Extension SampleExt 通过 Interface ISampleExt 提供服务给它的调用者 ClientApp。ClientApp首先通过 ISHELL_CreateInstance() 创建一个ISampleExt的实例,然后调用该接口实例的方法ISAMPLEEXT_xxx() 通过SampleExt提供的该功能,来实现特定的操作。这里只是通过 SampleExt 的 ISAMPLEEXT_JustSayHello() 来演示如何应用ISampleExt。ISampleExt和SampleExt的定义如图二所示。

 

 

图二、ISampleExt和SampleExt 的层次结构

 

       ISampleExt继承了IBase,SampleExt实现了ISampleExt。这里不详细介绍BREW中的COM模型,具体信息参看《BREW COM模型实战》。

 

       有了ISampleExt的接口形式,下面看该Interface的典型应用场景。

 

 

图三、SampleExt 的典型应用场景

 

2.2 文件组成

一个Module里可以有Applet,也可以有Extension,我们参照《BREW Applet 框架》中一个Module实现多个Applet那样来组织这个工程。不同之处是把其中一个Applet换成Extension,也就是在 Extension 这个 Module 里实现 ClientApp 和 SampleExt。

 

在ms vs60环境中通过BREW Application Wizard创建一个 Extension 工程,

并把工程的文件组织成图四所示。

 

 

图四、Extension工程中的文件

 

BREW装载Module里的Applet或Extension时,都会通过AEEClsCreateInstance() 函数,完成Applet或Extension的创建,我们可以在这个函数里面做些处理,根据不同的AEECLSID,来创建ClientApp或SampleExt的实例。

Factory.c文件中实现AEEClsCreateInstance() 函数,根据不同的AEECLSID,调用各自的构造函数来创建相应的实例。

ClientApp.c是Client Applet的对IApplet接口的实现。具体来说就是要实现事件处理函数,以及AddRef() 和Release() 函数,另外还要实现Factory 所引用的构造函数ClientApp_Constructor()。

SampleExt.c是SampleExt的实现。具体来说就是要实现ISampleExt中定义的方法,以及 Factory 所引用的构造函数SampleExt_Constructor()。

ClientApp.h 定义ClientApp类型。

CSampleExt.h 定义接口ISampleExt中的函数,和ISample的各种操作方法的方便店用形式ISAMPLEEXT_xxx(),以及SampleExt类型。

 

Extension 这个 Module 中要实现一个 Applet 和一个 Extension,所以要把这个Module的描述文件Extension.mif编辑成图五所示。

 

 

图五、编辑Extension.mif

 

2.3 Module Extension 中的关系

现在Factory 与 SampleExt和 ClioentApp之间的类图如下:

 


图六、SampleExt、ClientApp 以及 Factory 之间的关系

 

图中省略了AEEModGen,我们利用它来实现Module。

AEEClsCreateInstance() 是BREW 通过Module 创建 Module 内 Applet 或 Extension 的入口,这里我们把它定义在 Factory 中,它根据参数 ClsId 的值决定调用 ClientApp 还是 SampleExt 的 Constructor。

ClientApp 利用 AEEAppGen 实现Applet,并保留对 ISampleExt 的实例的引用。

 

2.4 实现Extension

2.4.1 类型定义

定义 ISampleExt

ISampleExt 继承 IBase,IBase 是 BREW 里所有 Interface 的基接口。在 ISampleExt中只是加入 JustSayHello() 方法。为了给调用者调用方便,定义操作ISampleExt的方法的三个宏 ISAMPLEEXT_AddRef、ISAMPLEEXT_Release 和 ISAMPLEEXT_JustSayHello。

 

typedef struct _ISampleExt ISampleExt;

    #define INHERIT_ISampleExt(iname) \
        INHERIT_IBase(iname); \
        void (*JustSayHello)(iname*)

    QINTERFACE(ISampleExt)
    {
        INHERIT_ISampleExt(ISampleExt);
    };

    /* These Macroes are provided for Client to Use */
    #define ISAMPLEEXT_AddRef(p) \
        AEEGETPVTBL((p),ISampleExt)->AddRef(p)

    #define ISAMPLEEXT_Release(p) \
        AEEGETPVTBL((p),ISampleExt)->Release(p)

    #define ISAMPLEEXT_JustSayHello(p) \
        AEEGETPVTBL((p),ISampleExt)->JustSayHello(p)

代码片断一、定义ISampleExt

 

定义 SampleExt

对比《BREW Applet 框架》中HelloBREW的定义,成员中没了 AEEApplet 这个Applet的缺省各种结构。由于没了AEEApplet,所以SampleExt中必须自己添加指向虚表的指针 pvt和引用计数m_nRefs。指向虚表的指针 pvt 必须在第一个成员位置,因为BREW默认的各种方法的操作都是基于这个指针指向的实现函数的虚表的。引用计数m_nRefs 是为了使这个组件能够被重复利用而采用计数所需设置的。关于BREW中的组件实现技术,参见《BREW COM的实现》。

 

    typedef struct _SampleExt {
        // First element of this structure must be pvt
        AEEVTBL(ISampleExt)   *pvt;

        // Reference Count
        int              m_nRefs;

        IDisplay        *m_pIDisplay;
        IShell          *m_pIShell;
        IModule         *m_pIMod;
    } SampleExt;

代码片断二、定义SampleExt

定义 ClientApp

ClientApp的定义参见《BREW Applet 框架》中Applet的定义,这里不再赘述。

 

2.4.2 AEEClsCreateInstance() 的实现

函数原型为:

int AEEClsCreateInstance(AEECLSID ClsId, IShell *pIShell, IModule *po, void **ppObj)

函数实现的主体根据不同的AEECLSID,调用 Applet 或 Extension 的构造函数来创建相应的Applet。

 

    switch (ClsId)
    {
    case AEECLSID_CLIEBTAPP:
        return ClientApp_Constructor(
                          ClsId,
                          pIShell,
                          po,
                          (IApplet**)ppObj);

    case AEECLSID_SAMPLEEXT:
        return SampleExt_Constructor(
                          ClsId,
                          pIShell,
                          po,
                          (ISampleExt**)ppObj);

    default:
        return EFAILED;
    }

    return (EFAILED);

代码片断三、Factory.c 中 AEEClsCreateInstance() 的实现

 

2.4.3 构造函数的实现

ClientApp 的构造函数

如同BREW提供的缺省的 AEEClsCreateInstance() 函数那样,ClientApp 在构造函数 ClientApp_Constructor() 里把事件处理函数ClientApp_HandleEvent() 和程序退出时的清理函数注册到BREW里。

 

SampleExt 的构造函数

如同BREW提供的缺省的 AEEApplet_New () 函数那样,把SampleExt 的构造函数 SampleExt_Constructor() 实现成下面的形式。

 

    SampleExt *pThis = NULL;
    AEEVTBL(ISampleExt) *pFuncs;
    int nSize = sizeof (SampleExt) + sizeof (AEEVTBL(ISampleExt));

    pThis = (SampleExt*)MALLOC(nSize);
    *ppObj = pThis;

    if (pThis == NULL)
        return ENOMEMORY;

    pFuncs = (AEEVTBL(ISampleExt) *)((byte*)pThis + sizeof (SampleExt));
    pFuncs->AddRef           = SampleExt_AddRef;
    pFuncs->Release          = SampleExt_Release;
    pFuncs->JustSayHello = SampleExt_JustSayHello;

    INIT_VTBL(pThis, ISampleExt, *pFuncs);

    pThis->m_nRefs = 1;
    pThis->m_pIShell = pIShell;
    pThis->m_pIMod = pIModule;
    pThis->m_pIDisplay = NULL;

    ISHELL_CreateInstance(pIShell,
                          AEECLSID_DISPLAY,
                          (void **)&pThis->m_pIDisplay);

    if (!pThis->m_pIDisplay)
    {
        // Cleanup
        FREE_VTBL(pThis, ISampleExt);
        FREE(pThis);
        return (EFAILED)
    }

    ISHELL_AddRef(pThis->m_pIShell);
    if (pThis->m_pIMod)
        IMODULE_AddRef(pThis->m_pIMod);

    return (AEE_SUCCESS);

代码片断四、SampleExt_Constructor() 的实现

 

这其中牵涉到BREW中的COM模型,这里暂不解释,详情参见《BREW COM模型实战》。

 

3.2.4 SampleExt 对<span style="font-size: 10.5pt; line-height: 173%; font-family: "Courier New";" lang=...


 
 

Things you can do from here:

 
 
Reply all
Reply to author
Forward
0 new messages