● ToolBox API徒然草(2006/05/13)

  このニュースは、MOSAの会員にのみ配布されているデベロッパー向けの
  デジタルマガジンMOSADeNのに掲載された記事です。ほぼ一ヶ月遅れで
  ここに掲載されて行きます

 〜 アプリケーションのUniversal Binary化(その6) 〜


今回は、Macintosh独自のデータ保存方法「リソース」についてエンディアンの影響を調べてみます。例題として、長い間QuickDrawで利用されてきた画像フォーマットのPicture(PICT)構造体を取り上げます。

まず頭に入れておかなければいけない点は、リソースデータはファイルのリソースフォークにビッグエンディアンとして保存されているということです。例えばリソースデータ内に何らかのサイズを示すlong値が含まれているとすると、その数値フォーマットは必ずビッグエンディアンです。リソースを取り扱う場合にResource ManagerのAPIを使えば、データのエンディアンの違いはシステムの内部処理が吸収しますので、x86環境においてもその違いを気にする必要はありません。ただし、APIを利用せず、直接リソースの内部データにアクセスするような場合には注意が必要です。

以下にx86環境でコンパイルすると正常に動かない例を示します。ここでの処理の対象はGetPicture()で読み込んだPICTリソース(PicHandle)です。setMyControlWellPict()は、PICTリソースをWellコントロール(画像表示用コントロール)に表示するためのルーチンです。Wellコントロールでは、その表示枠としてPICT画像の矩形枠(picFrame)を利用します。よって、矩形枠が大きすぎるPICT画像を小さなWellコントロールに表示する場合には、その矩形枠の再調整が必要になるわけです。setMyControlWellPict()ルーチンの引数fitに1を代入すると、PICT画像の矩形枠をWellコントロールの表示枠から上下左右3ピクセル分小さく合わせて表示することができます。



このルーチンがPowerPC用にコンパイルされれば正常動作しますが、x86用にコンパイルされると正常に動かず、画像は正しく表示されません。原因は、 srt=(*pict)->picFrameと(*pict)->picFrame=srtの箇所です。(*pict)->picFrameは生のリソースデータですので、その構造体のメンバー(4つのshort値)はビッグエンディアンです。しかし、それ以降のAPIが取り扱うRect構造体のメンバーはリトルエンディアンである必要がありますので、srt=(*pict)->picFrameという処理によりエンディアンの不整合が発生するわけです。

何らかのCarbon APIを用いれば、上記の問題はシステム側で解決してくれるはずです。そこで、PICT画像の矩形枠を得たり設定したりするAPIを探してみました。矩形枠を得るAPIとしては、QDGetPictureBounds()が見つかりましたが、どうもセットする方のAPIは存在しないようです。そこで、Rect構造体メンバーのエンディアンを反転するswapRect()と、PICT画像の矩形枠をセットするsetPictureBounds()という自作ルーチンを用意しました。



これでOKかと思われたのですが、調べてみるとQDGetPictureBounds()はMac OS X 10.3以上でないと利用できません(涙)。x86環境は必ずMac OS X 10.4以上ですので問題はないのですが、このルーチンをPowerPC環境のMac OS X 10.2xで動かすとクラッシュしてしまいます。そこで、PICT画像の矩形枠を得る場合にも、以下のような自作ルーチンを用意してやっと問題は解決しました。



とにかく、リソースデータを処理する場合には、そのために用意されているAPIを使うことが肝要です。ただし、Resource ManagerのAPI側でエンディアンを考慮してくれる対象は、Apple社が定義しているリソースタイプ(種類)だけですので注意してください。自分自身でデータフォーマット(構造体)を定義しているカスタムリソースについては、一般的なファイルを読み込む場合と同様、その入出力時にエンディアンの違いを考慮する必要があります。例えば、Metrowerks CodeWarrior付属のPowerPlant Frameworkで用いられているカスタムリソースなどがこれに当てはまります。

カスタムリソースデータと同様なものには、カスタムペーストボードデータやカスタムアップルイベントデータがあります。こうしたカスタムデータのエンディアンを効率よく反転させるために、Apple社はフリッパーと呼ばれるバイトスワップ用コールバックルーチンを組み込めるようにしました。仕組みは簡単で、OSTypeでその種類を判別できるバイトスワップ用コールバックルーチンを定義し、それをCoreEndianInstallFlipper()で登録します(CoreServiceのEndian.hを参照)。

フリッパーの仕組みやCoreEndianInstallFlipper()についての詳細は、以下のURLから参照できる「Universal Bynaryプログラミングガイドライン(第2版)」の「データのバイトスワップを行うコールバックの作成とインストール」の章に詳しく解説されています。また、Metrowerks CodeWarriorの付属のPowerPlant Frameworkのソースコードに対して考慮すべき処理内容は「Appendix D: PowerPlantの使用」の章で参照できます。

http://developer.apple.com/jp/transition/

次回は、もう少しリソースについての例題を調べてみます。また、効率の良いエンディアンの反転方法についても考えてみます。


copyright 2006 Ottimo, Inc. All rights reserved
無断転載・引用禁止
Contact us: koike@ottimo.co.jp