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

7 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简介

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

 

 

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

 

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

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

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 提供服务给它的调用者 ClientAppClientApp首先通过 ISHELL_CreateInstance() 创建一个ISampleExt的实例,然后调用该接口实例的方法ISAMPLEEXT_xxx() 通过SampleExt提供的该功能,来实现特定的操作。这里只是通过 SampleExt ISAMPLEEXT_JustSayHello() 来演示如何应用ISampleExtISampleExtSampleExt的定义如图二所示。

 

 

图二、ISampleExtSampleExt 的层次结构

 

       ISampleExt继承了IBaseSampleExt实现了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里的AppletExtension时,都会通过AEEClsCreateInstance() 函数,完成AppletExtension的创建,我们可以在这个函数里面做些处理,根据不同的AEECLSID,来创建ClientAppSampleExt的实例。

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

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

SampleExt.cSampleExt的实现。具体来说就是要实现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之间的类图如下:

 


图六、SampleExtClientApp 以及 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 继承 IBaseIBase BREW 里所有 Interface 的基接口。在 ISampleExt中只是加入 JustSayHello() 方法。为了给调用者调用方便,定义操作ISampleExt的方法的三个宏 ISAMPLEEXT_AddRefISAMPLEEXT_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