連載
» 2009年09月15日 00時00分 公開

“BREW”アプリケーション開発入門(3):BREWアプリケーションの構成を理解しよう! (2/3)

[末永貴一(エイチアイ),@IT MONOist]

IAppletインターフェイス

 インターフェイスの実装は、「AEEAppGen.c」の中でも行われています。この「AEEAppGen.c」の中で行われているのが、「IAppletインターフェイス」の実装です。

 IAppletインターフェイスの実装により、BREW AEEはBREWアプレットへのアクセスが可能になります。

 この実装は、以下の関数内で行われます。


boolean AEEApplet_New(int16 nIn,
                      AEECLSID clsID,
                      IShell * pIShell, 
                      IModule * pIModule, 
                      IApplet **ppobj, 
                      AEEHANDLER pAppHandleEvent,
                      PFNFREEAPPDATA pFreeAppData) 

 「AEEApplet_New()」は、「hello.c」の中にあるインスタンス生成の関数である「AEEClsCreateInstance()」の中で呼ばれ、IAppletインターフェイスの実装などを行います。

 IModuleインターフェイスの実装と同様に、IAppletでもBREW AEEからのアクセスを可能にするために、以下のインターフェイスの実装が行われます。

インターフェイス 実体の関数
IAPPLET_AddRef() AEEApplet_AddRef()
IAPPLET_Release() AEEApplet_Release()
IAPPLET_HandleEvent() AEEApplet_HandleEvent()

AEEApplet構造体

 このIAppletインターフェイスの実装のほかに重要なのが、「AEEApplet構造体」の初期化です。AEEApplet構造体は「アプレット構造体」とも呼ばれ、BREWアプリケーションの情報などを保存するための構造体でもあり、アプリケーション内でのデータの受け渡しに利用される構造体でもあります。

 BREWでは、“グローバル変数やstatic変数を利用することが仕組み的に禁止”されています。そのため、アプリケーション内でのデータの受け渡しを行うために、アプレット構造体を利用します。実際には、AEEApplet構造体を拡張したアプリケーションごとの構造体を利用します。

 例えば、HelloWorldプログラムであれば、「hello.c」に定義されているhello構造体がそれに該当します。

typedef struct _hello {
        AEEApplet      a ;  ←★AEEApplet構造体のポインタ★
        AEEDeviceInfo  DeviceInfo;
        // これ以下に任意のデータを指定
} hello; 

 この構造体を拡張利用すれば、アプリケーション内でデータの受け渡しを行うことができます。拡張の際には、コメントにあるように構造体のメモリマップの下位に任意のデータを配置する必要があります。これはBREW AEEが動作上、AEEApplet構造体のメモリマップを維持しなければならないためです。

イベント処理

 作成されたIAppletインターフェイスの役割で特に重要なのがイベント処理です。

 BREWアプリケーョンは、基本的にイベントドリブン型のプログラムです。そのため、イベントの通知を実行環境であるBREW AEEから受け取る必要があり、そのイベント通知を受け取るための処理がIAppletインターフェイスの実装にあります。

 実際に、BREWアプリケーション内でイベント処理を記述しているのが、「hello.c」の中にある「hello_HandleEvent()」の中です。「hello_HandleEvent()」では、BREW AEEから上がってくるイベントコードに対して処理を記述していきますが、この「hello_HandleEvent()」の呼び出しが、IAppletインターフェイスを介して行われています(図4)。

イベント処理について 図4 イベント処理について

 BREW AEEは、イベントが発生するとBREW AEEのイベントキューに、そのイベントをストックしていきます。イベントキューにたまったイベントは、「IAPPLET_HandleEvent()」を介して非同期に順次通知されますが、このときに各イベントに対応したイベントコードが、BREWアプレットに渡されます。

 渡されたイベントコードを最終的に処理する関数である「hello_HandleEvent()」の呼び出しは、「IAPPLET_HandleEvent()」の実体の関数である「AEEApplet_HandleEvent()」を介して行われます。この動作は、「AEEApplet_New()」の中で「hello_HandleEvent()」が「AEEApplet_HandleEvent()」と関連付けられることによって機能します。ソース中では「hello.c」の「AEEClsCreateInstance()」の中で「AEEApplet_New()」の引数に「hello_HandleEvent()」の関数ポインタが渡されている部分です。これはアプレットごとのイベント処理関数を後から登録できるようにする仕組みで、アプレットの実装にBREW AEEが依存しない構造になっているためです。

if( AEEApplet_New(sizeof(hello),
                  ClsId,
                  pIShell,
                  po,
                  (IApplet**)ppObj,
                  (AEEHANDLER)hello_HandleEvent,  ←★イベント関数の登録★
                  (PFNFREEAPPDATA)hello_FreeAppData) ) 
hello.c(抜粋)

 留意していただきたいのですが、BREWのイベントは同時に複数を処理できません。また、イベント処理に時間がかかってしまった場合、イベントキューからイベントがあふれる現象が起こる可能性があり、その場合、そのほかのイベントは破棄されることになります。そのため、イベント処理するプログラム側は処理時間を短くコントロールすることが必要になり、長時間かかるようであれば処理を分割するなどして、時間を短くする必要があります(注4)。

※注4:BREWは、“ノンプリエンティブマルチタスク”と考えることができ、アプリケーションはシングルスレッドで動作します。そのため、プログラマがアプリケーション側でタスクの制御をある程度考慮してプログラミングする必要があります。


 また、イベントのプライオリティに関してはBREWのバージョンにより異なります。BREW3系ではイベントのプライオリティはありませんが、BREW2系ではいくつかのプライオリティの高いイベントがあるなど、バージョンにより動作が異なります。そのため、対象となる端末がBREWのどのバージョンをサポートしているかを考える必要があります。

 ここで説明したインターフェイスは、BREW AEEからBREWアプリケーションへのアクセスを可能にするものですが、インターフェイスの役割としてはBREWアプリケーションからBREW AEEへのアクセスも含まれます。つまり、BREWのインターフェイスはBREW AEEとBREWアプリケーションの双方向のアクセスを共通化した仕組みであるということになります。

 IModuleやIApplet以外にもインターフェイスは多くありますが、BREW内では命名規則により先頭に大文字の“I”が付く名前の機能は、インターフェイスであることを表していますので、名前からインターフェイスであるかどうかを判断できます(そのほかのインターフェイスについては、随時解説していきます)。

Copyright © ITmedia, Inc. All Rights Reserved.