2006-03-07
目次
「WebObjects Dev Report」 第42回 田畑 英和
2/18にApple Store Shinsaibashiで開催されたKansai Developer’s Nightには多くの方々にご参加いただきありがとうございました。きっと2回目も開催されるかと思いますので、今回参加できなかった方もぜひ次回はご参加いただければと思います。
◇アダプターのUniversal Binary対応
さて、今回からは数回にわたってWebObjectsアプリケーションの運用について解説していきたいと思います。まずは実行環境から確認しておきます。すでにIntel Macの出荷が始まっており、入手済の方もいらっしゃるかと思いますが、WebObjectsはJavaでプログラミングをおこない、Javaプログラムであれば基本的にはPower PCのMacでもIntelのMacでも動作します。
しかし、WebObjectsの実行環境には一部C言語で実装されたプログラムがあります。WebサーバとWebObjectsアプリケーションを連携する「アダプター」と呼ばれるプログラムがそれなのですが、この「アダプター」がUniversal対応しているかどうかを確認してみました。なお「アダプター」にはApache用のアダプターとCGI用のアダプターの2種類がありますので、両方とも確認を行ったところ以下のようになりました。
・Apache用アダプター
% pwd
/System/Library/WebObjects/Adaptors/Apache
% file mod_WebObjects.so
mod_WebObjects.so: Mach-O fat file with 2 architectures
mod_WebObjects.so (for architecture i386): Mach-O bundle i386
mod_WebObjects.so (for architecture ppc): Mach-O bundle ppc
・CGI用アダプター
% pwd
/Volumes/Tiger/System/Library/WebObjects/Adaptors/CGI
% file WebObjects
WebObjects: Mach-O fat file with 2 architectures
WebObjects (for architecture i386): Mach-O executable i386
WebObjects (for architecture ppc): Mach-O executable ppc
このように両方とも2つのアーキテクチャをサポートしていることが分かります。ただし、現状ではまだMac OS X ServerをサポートしたIntel Macがないために、Mac OS X Serverで運用を行うにはPower PCベースのMacが必要になります。なお今回は、Tiger上にXcode2.2をインストールした環境で確認を行っています。
◇wotaskd
次にWebObjectsの運用環境を構成するファイルやディレクトリの確認を行っておきましょう。Tiger Serverを前提として話を進めますが、Tiger Serverではデーモンプログラムの起動の仕組みが変更になっています。WebObjectsの運用環境ではwotaskdというデーモンが動作していますが、このwotaskdをシステム起動時に起動するには以下のplistファイルを用います。
・wotaskdのplist
/System/Library/LaunchDaemons/com.apple.wotaskd.plist
このplistファイルの内容に基づいてlaunchdがwotaskdを起動します。システム起動時にwotskdを起動するかどうかは、このplistファイルを直接編集しなくても、「サーバ管理」というMac OSX Server用の管理ツールから設定することができます。
といいましても設定が必要なパラメータといえばwotaskdが使用するポート番号程度で、あとはサービス開始ボタンをクリックするだけでwotaskdが起動するようになります。
wotaskdはXML形式の設定ファイル”SiteConfig.xml”を必要とし、このファイルは次のパスに保存されます。
・wotaskdの設定ファイルのパス
/Library/WebObjects/Configuration/SiteConfig.xml
wotaskdはappserverユーザ権限で動作するため、appserverユーザに対して/Library/WebObjects/Configuration/へのアクセス権が与えられている必要があります。もし適切なアクセス権が設定されていないとwotaskdは起動に失敗します。また、wotaskdは次のパスにインストールされています。
・wotaskdのパス
/System/Library/WebObjects/JavaApplications/wotaskd.woa
◇Web Server Resources
WebObjectsではアプリケーションをインストールするときに、画像ファイルなどのWeb Server ResourcesをWebサーバ上に直接配置し、それ以外のJavaプログラムなどのファイルを別の場所に配置するSplit Installを行います。
アプリケーションとフレームワークでインストール先が若干異なりますがそれぞれ以下のパスにWeb Server Resourcesをインストールします。
・アプリケーションのWeb Server Resourcesのパス
/Library/WebServer/Documents/WebObjects/
・フレームワークのWeb Server Resourcesのパス
/Library/WebServer/Documents/WebObjects/Frameworks
ちなみにアプリケーションのインストール先ですが、任意のパスにインストールすることもできますが、次のパスにインストールするのが一般的です。
・アプリケーションのインストール先
/Library/WebObjects/Applications
◇フレームワーク
アプリケーションを開発するさいに、オープンソースのフレームワークを使用する場合もあるでしょうし、独自に開発したフレームワークを使用するような場合もあるでしょう。フレームワークは通常次のパスにインストールします。
・フレームワークのインストール先
/Library/Frameworks/
◇Monitor
WebObjectsには運用環境の設定をおこなうWebアプリケーション「Monitor」が付属しています。「サーバ管理」を使ってシステム起動時に「Monitor」を自動起動することもできますが、必要に応じて手動で起動することもできます。
Monitorを手動で起動するときは、以下のパスにある「Monitor」の起動スクリプトを実行します。
・Monitorの起動スクリプト
/System/Library/WebObjects/JavaApplications/JavaMonitor.woa/Monitor
というわけで、今回はWebObjectsの運用環境について解説してきました。次回はアプリケーションのインストールなどについて解説する予定です。
小池邦人のCarbon API 徒然草(2006/03/03)
今回は、PowerPC用のソースコードをUniversal Binary化する時に注意すべき点をピックアップしてみます。最大の関門は、 PowerPCとx86 CPUのエンディアンの違いを克服することですが、それ以外にも色々な要因が存在します。
エンディアンの問題を含め、Universal Binary化でのソースコードの書き換えは、ほとんどがPowerPCとx86 CPUのアーキテクチャの違いにより生じます。以下に対象となるCPUアーキテクチャの違いをピックアップしてみました。
1.エンディアンの違い(PPCはビッグエンディアンでx86はリトルエンディアン)
2.AltiVecユニットの有無の問題(x86 CPUではSSE/SSE2に切り換える必要あり)
3.ゼロで割ったときの処理が異なる(PowerPCは結果がゼロでx86はクラッシュする)
4.変数アレンジメント(PowerPCは4Byteや16Byteだがx86は1から10Byteの可変)
5.構造体とUnionのアレンジメントに違いがある
6.整数演算オーバーフロー時の代入値の違い(PowerPCは0x7fffffff、x86は0×80000000)
7.データ長の違い(x86はlong doubleが80Bits、boolはx86が1ByteでPowerPCは4Byte)
8.浮動小数点の比較に違いが生じる時がある(オーバーフローなどの扱い)
9.関数の呼び出し時の引数(引数の積み方x86ではスタックへPowerPCではレジスタへ)
10.ビットフィールドの扱いが異なる(これはコンパイラの仕様にもよる)
これら以外にもまだ幾つか存在しているかもしれませんが、ソースコードに影響が出ると考えられる要因についてはこれぐらいでしょう。一番影響が大きいのは1番ですが、画像処理の高速化などにAltiVecコードをバリバリ用いているソースコードでは、2番も大きな問題となります。逆に、AltiVecをまったく利用していなければ、2番に関しては何も気にする必要はありません。3番に関してはあってはいけないミスです。通常は、事前にゼロで割ることは避けるように処理されているべきで、そうでないと、x86 CPUはクラッシュします。どちらかと言うと潜在的に存在していたバグだと考えて対処すべきでしょう。
4番と5番も大きな問題ですが、68K CPUからPowerPCへソースコードを移植した経験のあるデベロッパは、すでに対策済みのソースコードを用いているはずですので、それほど心配はないでしょう。今のところ、筆者もこの2つの要因にひっかかりソースコードに手を入れたことはありません。数多くのアプリケーションをUniversal Binary化してきた経験上、それ以外の要因については、通常あまり気にする必要はなさそうです。ただし、今回の話は、あくまでも筆者のソースコードの「書き方」に限定されますので、各人それぞれ注意を怠らないようにしていただきたいと思います。
上記の要因に対処していないと、いかなる結果が起こるのか予想してみましょう。まず1番のエンディアンの違いが無視されていると…クラッシュする、計算結果が異なる、画像のカラー表示が異常、Unicode(複数バイト文字)テキストが正しく表示できない、バイナリファイルが正しく読み書きできない、ネットワークによるデータのコミュニケーションが正しく行われない、などなど数多くのトラブルが生じます。AltiVecコードを利用していれば、x86用コンパイル時にエラーが表示されます。また、それ以外の要因を無視した結果としては、分岐処理の異常やクラッシュなどが考えられます。
こうして調べてみると、やはり「エンディアンの違いの克服」を達成すれば、Universal Binary化の仕事は90%完了することが理解できると思います。ただし、ソースコードに一カ所でも対処し忘れの箇所が存在すると、それが大きなバグとして残りますので、細心の注意をはらい対応箇所を探し出す必要があります。特に画像関連のアプリケーションをUniversal Binary化していると感じるのですが、このエンディアンへの対処、本当にひとつひとつ「つぶす」という表現がピッタリと当てはまる根気のいる作業です。
次に、もうほとんどの皆さんは理解されていると思いますが、復習として「エンディアンの違いとは何か?」を簡単におさらいしておきます。PowerPCの場合には2Byte、4Byte、8Byteの数値は、そのバイト順にメモリに格納されますがx86の場合には逆順に格納されています。この数値のメモリへの格納方法の違いがエンディアンの違いを示し、バイト順通りに格納される方をビッグエンディアンと呼び、逆順で格納される方をリトルエンディアンと呼びます。
unsigned long value;
unsigned char *cptr;
unsigned char cc;
value=0x12345678;
cptr=(unsigned char *)&value;
cc=*cptr;
上記ソースコードでは、valueというunsigned long(4Byte)に16進の0×12345678を代入しています。そして、valueの先頭アドレスをキャストを使いポインタのcptrに代入し、その先頭アドレス1Byteのみをunsigned charのccに代入しています。処理後、何らかの方法でccの内容を表示してみると、PowerPC(ビックエンディアン)では0×12と表示されますが、x86(リトルエンディアン)では0×78と表示されます。この表示結果から、x86ではunsigned longの数値の最終バイトから順にメモリに格納されていることが良く分かります。ちなみに…
cc=*(cptr+1);
とすると、PowerPCでは0×34と表示され、x86では0×56という表示結果になります。
ところで、ビッグエンディアン、リトルエンディアンと言う呼び名の由来はどこから来たのでしょうか? どうも、ガリバー旅行記に登場するとある王国が、卵をとんがった(小さい)方から食べる派閥と、膨らんだ(大きい)方から食べる派閥に分裂していたという逸話が発端のようです(笑)。
何故ガリバー旅行記から引用されたかは謎なのですが、そんな面白い由来も「Universal Binary Programming Guidelines」で紹介されています。
次回は、PowerPCとx86 CPUのエンディアンの違いによる影響を、サンプルアプリケーションのソースコードを調べながら検証していきたいと思います。数値のバイト順がひっくり返りメモリに格納されるという摩訶不思議な体験(まあそう思うのは純正マックデベロッパだけですが…)をしてみたいと思います。
つづく
SqueakではじめるSmalltalk入門 第57回 鷲見 正人
本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。前回はサブモーフやサブモーフ化という仕組みを取り上げました。そこで、このサブモーフ化という仕組みをふまえて、いま一度、ポップアップメニューやウインドウがどのような構成になっているかを調べてみましょう。まずはポップアップメニューから。
ポップアップメニュー(メニューモーフ)は、たとえば、次のようなスクリプトで簡単に記述することができます。
| menu |
menu := MenuMorph new.
menu defaultTarget: 1.
menu add: 'default (one)' action: #inspect.
menu addLine.
menu add: 'two' target: 2 selector: #inspect.
menu add: 'three' target: 3 selector: #inspect.
menu add: 'four' target: 4 selector: #inspect.
menu addLine.
menu
add: 'open workspace'
target: Workspace
selector: #openLabel:
argument: 'My New Workspace'.
menu invokeModal
このスクリプト全体を選択しdo it(cmd + D)すると、その場に次の図に示すようなメニューが現れます。
[fig.A]スクリプトで作られたポップアップメニュー
http://squab.no-ip.com:8080/mosaren/uploads/57a.png
もちろん格好だけではなく、メニューとしてきちんと機能します。「default (one)」を選択すると「1」のインスペクタが、「two」「three」「four」ではそれぞれ「2」「3」「4」のインスペクタが表示されます。最後の「open workspace」では「My New Workspace」というタイトルの付いた新しいワークスペースが現れます。
ポップアップメニューのモーフとしての“姿”と“振る舞い”を確認できたところで、今度は先ほどのSmalltalkで記述されたスクリプトの中身を読み下してみましょう。
このスクリプトでは最初で、テンポラリ変数「menu」にa MenuMorph(MenuMorphのインスタンス)を束縛しています。MenuMorphは、その名の示すとおり、メニューの役割を果たすモーフの属するクラスです。
このmenu(に束縛されているa MenuMorph)にメニュー項目(a MenuItemMorph)や区切り線(a MenuLineMorph)をサブモーフ化することでメニューは構成されています。ですが、いちいちメニュー項目や区切り線の細かな仕様を決めてサブモーフ化するのは大変なので、#add:action:(あるいは、#add:target:selector:、#add:target:selector:argument:)や、#addLineという便利メソッドを起動するメッセージを最低限のパラメータを添えて送信することで、そのような面倒な“手続き”に代えています。
たとえば、メッセージ「addMenu」で起動する「MenuMorph >> #addLine」メソッドの定義は、次のようになっています(スクリプト中の「addLine」部分を選択して、browse it(cmd + B)で呼び出せます)。
MenuMorph >> addLine
submorphs isEmpty ifTrue: [^ self].
(self lastSubmorph isKindOf: MenuLineMorph)
ifFalse: [self addMorphBack: MenuLineMorph new].
ここで「submorph」は、すべてのモーフが持つインスタンス変数で、そのモーフに登録されたサブモーフたちを収めた配列を束縛しています。したがってこのメソッドには、「項目が何もないメニュー、あるいは、最後のサブモーフが区切り線の場合は手を付けず、それ以外なら、区切り線をサブモーフとして追加する」という内容が記述されていることを読み取ることができるでしょう。どうです(#addMorph:こそ起動していませんが)ちゃんとサブモーフ化の手続きがとられていますね。メソッド(#add:target:selector:argumentList:)をひとつ介しますが、メニュー項目(#add:action:)についてもしかりです。
メニュー項目(a MenuItemMorph)を追加するメソッドはいくつかありますが、最低限、メニュー項目に付けるラベル(文字列)と、その項目を選択されたときに送るメッセージのセレクタ(シンボル)を引数として渡してあげる必要があります(#add:action:)。ターゲットを指定しない場合は、メニューが把握しているデフォルトのターゲットに指定したセレクタを含むメッセージが送信されます。デフォルトターゲットは初期状態ではnilですが、メニューに「defaultTaget: …」を送信することで変更可能です。
今回作成したメニューでは、デフォルトターゲットに「1」を指定しています(defaultTarget: 1)ので、ターゲットを明示的にせずにサブモーフ化されたメニュー項目「default (one)」では、その選択時にメッセージ「inspect」が「1」に送信されます。結果、「1」のインスペクタが現れる…というカラクリです。実際のアプリケーションでは、このメニュー選択をトリガーにして行ないたい事柄を体現するメッセージを、それにふさわしいオブジェクト(ターゲット。たいていはアプリケーションのモデル)に送るよう指示しておけばよいことになります。
ターゲットはメニュー項目ごとに変えることもできます。それが「two」から「four」までの例です。それぞれ、第二パラメータ(第二引数)に希望するターゲット(「2」か「3」か「4」)を添えて、#add:target:selector:というメソッドを起動するメッセージをmenuに送信しています。
ターゲットに送信するメッセージにパラメータが必要な場合は、#add:target:selector:argument:を起動するメッセージを送ります。最後の「open workspace」がその例です。新しいワークスペースを開きたいときには、Workspaceに「openLabel: titleString」というメッセージを送るのですが、メッセージ「inspect」と異なり、この際、ウインドウタイトルを明示的にするためのパラメータ(例では’My New Workspace’)が必要になります。menuへのメッセージ送信時にはこれを第三パラメータとして添えています。さらに多く(2つ以上)のパラメータが必要なメソッドを起動したいとき向けには、「add: itemString target: targetObject selector: selector argumentList: argArray」というメッセージも用意されています。
次回は、このメニューをモーフとしてバラバラに分解してみて、メニュー項目モーフの中身がスクリプトでの注文通りの仕様になっているのかを確認してみましょう。
バックナンバー:
http://squab.no-ip.com:8080/mosaren/
二ュース・解説
今週の解説担当:木下 誠
———————————————————————-
Ruby on Railsの紹介
———————————————————————-
Webアプリケーションのフレームワークとして、最近急速に注目を集めているのが、Ruby on Rails。Ruby をベースにしていて、高速なアプリケーション開発ができるのが特徴です。この Ruby on Rails を紹介するドキュメント「Using Ruby on Rails for Web Development on Mac OS X」が ADC で公開されました。
もともと、Mac OS XにはRuby環境が標準で添付されているので、相性はいいはずです。その証拠に、このドキュメントの最後に参考文献として「Agile Web Development with Rails」という本が紹介されていますが、この本の図版はすべて Mac OS X上で動かしたものになっています。
UNIXベースのため、このような新しい動きにすぐついていけるのが、Mac OS Xの大きな利点でしょう。しかし、こういう記事が ADC で紹介されると、「WebObjectsの立場は?」と突っ込んでみたくなりますが。
Using Ruby on Rails for Web Development on Mac OS X
http://developer.apple.com/tools/rubyonrails.html
Agile Web Development with Rails
http://pragmaticprogrammer.com/titles/rails/index.html
———————————————————————-
USBソフト開発のQAが更新
———————————————————————-
USBソフトの開発に関するQA「Common QA and Roadmap for USB Software Development on Mac OS X」が更新されました。UHCIのサポートに関する記述が追加されています。
もともと、Mac OS XではOHCIとEHCIがサポートされていました。これが、Mac OS X 10.4になってから、UHCIのサポートが加わりました。今から考えると、これがIntel Mac登場の布石だったのかもしれません。Intel Macでは、UHCIとEHCIが使われています。
QA1370: Common QA and Roadmap for USB Software Development on Mac OS X
http://developer.apple.com/qa/qa2004/qa1370.html
———————————————————————-
ホットキーに関するサンプル
———————————————————————-
ホットキーを使ってiTunesをコントロールするサンプル、iTunesControllerが公開されました。
iTunesのコントロールを行うことのできるソフトですが、主眼はホットキーの扱い方におかれています。ホットキーをコントロールするために、RegisterEventHotKey、UnregisterEventHotKey、CGPostKeyboardEvent、といったAPIを使用しています。iTunesのコントロールは、AppleScriptを使っています。
iTunesController
http://developer.apple.com/samplecode/iTunesController/iTunesController.html
MOSAからのお知らせと編集後記は割愛します