{{category 開発情報}} {{category 陰郎の書いた記事,nolink}} !!!【C++】 ARMlet 対応に関するデザインメモ !!概要  Palmware を ARMlet 対応にする場合、Palm OS 5 専用にしない限りは既存 68K コードのサポートも続行する必要があります。また、Palm OS シミュレータでも高速に動作させる必要がある場合、その対応も必要になります。このページでは、このような状況におけるデザインの選択肢を提示します。 !!デザインの説明  まず、ARMlet 化すべき処理を抽象化するクラスを作成します。ここでは、クラス名は IntensiveFunction とします。 class IntensiveFunction { public: virtual int Execute( OperationData& opData ) = 0; };  このクラスは抽象クラスですから、インスタンスを作成することはできません。ここから 68K コード、ARM コード、Palm OS Simulator 用のコードをそれぞれ実装する派生クラスを作成することになります。そして、それらの各種環境を識別して適切な派生クラスのオブジェクトを返すファクトリクラスユーティリティも作成します。 class IntensiveFunctionFactory { public: static IntensiveFunction* Create( ); };  こうすることで、呼出し側で実行環境を気にせずに処理を呼び出すことができるようになります。 IntensiveFunction* pFunction = IntensiveFunctionFactory::Create( ); pFunction->Execute( opData );  となると、問題は IntensiveFunctionFactory::Create( ) においてどのような実装をすればよいかになります。その準備として、実行環境の特性を取得するためのクラスユーティリティとして DeviceTraits を準備し、列挙値やサービス関数を用意します。 DeviceTraits { public: enum PlatformType { PLATFORM_LEGACY68K = 0, PLATFORM_ARM = 1, PLATFORM_SIMULATOR = 2 }; public: static PlatformType GetPlatFormType( ); };  DeviceTraits::GetPlatFormType( ) を呼び出すことで、68K 環境なのか ARM 環境なのか、はたまた Palm OS Simulator 環境なのかがわかるわけですね。このメソッド自体をどう実装すれば良いかについては、「 Palm OS Programmer's Companion 」の 341 ページあたりにサンプルコードがあるのでそちらを参照してください。  で、これを利用することで IntensiveFunctionFactory::Create( ) は以下のように実装できます。Palm OS Simulator 用のネイティブ DLL を用意しないのであれば、PLATFORM_SIMULATOR に対して IntensiveFunction68K を返すようにすれば良いでしょう。 IntensiveFunction* IntensiveFunctionFactory::Create( ) { IntensiveFunction* pFunction = NULL; switch( DeviceTraits::GetPlatFormType( ) ) { case DeviceTraits::PLATFORM_LEGACY68K: pFunction = new IntensiveFunction68K; break; case DeviceTraits::PLATFORM_ARM: pFunction = new IntensiveFunctionARM; break; case DeviceTraits::PLATFORM_SIMULATOR: pFunction = new IntensiveFunctionPalmOSSim; break; } return pFunction; }  この IntensiveFunctionFactory::Create( ) に対してなんらかのパラメータを渡すことで、強制的に 68K コードで動作させるようなことも可能です。それにより、ARM 環境でも 68K コードで動作させて体感速度を比較する、などといったことも可能です。  さて、残るはそれぞれの環境向けの IntensiveFunction 派生クラスをどのように実装するかです。このページはデザインの提示が目的なのでコードの詳細には触れませんが、ARM 版や Simulator 版では API 関数 ::PceNativeCall( ) を使用するということだけはコメントしておきます。 class IntensiveFunction68K : public IntensiveFunction { public: virtual int Execute( OperationData& opData ){ // 通常の 68K コード }; }; class IntensiveFunctionARM : public IntensiveFunction { public: virtual int Execute( OperationData& opData ){ // ::PceNativeCall( ) 経由で ARMlet 呼び出し }; }; class IntensiveFunctionPalmOSSim : public IntensiveFunction { public: virtual int Execute( OperationData& opData ){ // ::PceNativeCall( ) 経由で Windows DLL 呼び出し }; };  以上です。いわゆる Abstract Factory パターンを使用しているだけなので、難しいことはないでしょう。これはあくまで1つの選択肢としてのデザインですから、他の方法と比べて優れているかどうかといった主張をするものではありません。 !!参考情報  このページの情報は、筆者が自分の weblog で過去に書いた以下の情報をベースに作成しました。上記デザインのクラス図も掲載しているので参考にしてください。 http://www.project-enigma.jp/members/kagelow/locus/archives/2006/03/armlet.html  また、このページで提示したデザインを実際に使用して ARMlet 対応をした Palmware が以下の場所にあります。 http://www.project-enigma.jp/products/PalmLife !!コメント  このページの情報に関する誤りや追加情報がありましたら、コメントをお願いします。 {{comment}}