Mozilla meets Python without rebulding
2008.01.17 Thursday 21:54
Miroを見ながら考えた.「ひょっとして,Xul + Pythonも結構いけるんじゃないか」.メモリ使用量で見るとXulRunner(Mozilla Runtime)が15MBに対して,wxPythonが18MB.素のPythonは4MBなのでそれを加えて19MB.Mozillaの表現力を持ってこのサイズならそんなに悪くない.XulRunnerがMozillaのレンダリングエンジンとXulによる拡張性を備えていて,Mozillaと同様の技術で開発できる点も魅力だ.
MozillaとPythonをつなぐPyXPCOMが標準では含まれておらずリビルドが必要で,しかもコンパイラが限定されているというので一旦はあきらめたが,Miroからバイナリファイルをもらってリビルド無しで何とか環境ができたという話.
MozillaとPythonをつなぐPyXPCOMが標準では含まれておらずリビルドが必要で,しかもコンパイラが限定されているというので一旦はあきらめたが,Miroからバイナリファイルをもらってリビルド無しで何とか環境ができたという話.
昨日
PyXPCOMは最新のMozillaソースコードには含まれているがXulRunner配布パッケージには含まれていない.普通ならコンパイルが必要になるのだが,PyXPCOMはMozillaだけでなくPythonにも依存している.python.orgで配布されている2.5.1がmsvcrt71.dllに依存しているので,公式のPythonを使うためにはMozillaもmsvcrt71.dllでコンパイルする必要がある.つまりVisual Studio .NET 2003が必要.
VC2005ではmsvcrt80.dllを使うからだめなのだ.嗚呼,DLL Hell...
本日
ふと思い立って,Miroのパッケージをのぞくとxulrunnerが含まれており,都合の良いことにmsvcrt71.dllを使っている.ということは(たぶん丸ごとそのまま使っても良いかもしれないけど一応)必要なファイルをピックアップして公式に配布されている1.8.0.4のパッケージに追加すればPyXPCOMが動くのではないか?というのが出発点.
Miroから取り出したファイル
Pythonは公式2.5.1を別途インストール済みであることを前提とする.(python25.dllがパスに含まれていること)
XulRunnerは1.8.0.4を前提とする.1.9系列はVC 2005でコンパイルされているので不可.
ftp://ftp.mozilla.org/pub/mozilla.org/xulrunner/releases/
コンポーネントを自作するためにはidlファイルを含むGecko SDKも必要となる.
http://developer.mozilla.org/en/docs/Gecko_SDK
Participatory Culture Foundation/Miro/xulrunner 配下の以下のファイルを使う.
* python/xpcom/*
→ Pythonのライブラリパス(site-lib等)へそのままコピーする
* components/pyloader.dll
→ Pythonで書かれたコンポーネントを実行するために必要.
* regxpcom.exe, xidl.exe, xpcshell.exe
→ コンポーネント作成で使う
これらのファイルはMiroをインストールしなくても,以下の場所から入手可能
https://svn.participatoryculture.org/svn/dtv/trunk/dtv-binary-kit
使ってみる
基本的なstep by stepの説明はMozilla Development Centerに例があるので,ここには概略のみ記す.
[Step1] ファイルの配置 (ディレクトリ構成)
/program
xul-stub.exe
/xulrunner (そのまんま+追加ファイルを入れる)
application.ini
/chrome (プログラム本体)
/defaults (Preference本体)
/skin (css等)
起動時に
xulrunner/xulrunner.exe {application.iniのパス}の代わりにxul-stub.exeを{好きな名前}.exeに変更して利用可能.このスタブは同一ディレクトリのapplication.iniとxulrunner/xulrunner.exeを自動で見つけてくれるようだ.
application.ini の中に Vendor, Nameを設定するが,この名前は個人用ディレクトリのディレクトリ名として使われる.
xulrunner --register-globalを実行すると,xulrunnerがこの場所になくてもスタブがxulrunnerを呼び出せるようになるが,予期しないxulrunnerが使われる可能性があるのでこれは非推奨.
[Step2] idlインターフェース
IDLインターフェースを定義する.その際nsISupports.idlをインクルードするためにGecko SDKが必要となる.
xpidl.exeにかけるとidlと同じディレクトリに拡張子が".xpt"のファイルが生成されるので,それはxulrunner/componentへ入れる.(本当はxulrunnerとは別のcomponentディレクトリへ入れて分離したいが,そこまでできていない)
idlに記述するGUIDはmicrosoft SDKに含まれるGUIDGEN.exeを使うか,またはGUID Generatorサービスを使ってファイルごとに生成する.
Gecko SDKに含まれるxpidl.dllは未解決の外部依存があって使用できないので,Miroに含まれる物を使う.
[Step3] コンポーネント本体
これもxulrunner/components/{好きな名前}.py として作成する.名前は何でも良いようだ.Step2で作ったインターフェースの名前が,Pythonのクラスの中で
_com_interfaces_ = components.interfaces.{インターフェース}
として利用される.また,_reg_clsid にはGUIDを生成して設定する.
[Step4] 使えるようにする
xulrunner/componentsディレクトリでregxpcom.exeを実行するとcompreg.dat, xpti.datの2つが作られる.いずれもテキストファイル.xpti.datにidlのインターフェース名が含まれ,compreg.datに生成したpythonコンポーネントが含まれていれば成功.
pythonスクリプトに文法エラーがある場合は,この段階で検出される.エラーになったらスクリプトを修正し,2つのdatファイルを削除して再チャレンジする.
[Step5] ちょっと試す
XULの実行中にJavaScriptエラーになった場合,そこで処理が打ち切られるだけなので,原因がつかめない.xpcshell.exeでインタラクティブにJavaScriptを実行できるので,コンポーネントのロードとインターフェースの呼び出しがうまくできるかをコマンドラインで試してみるとよい.ここでエラーが発生した場合はエラーメッセージが見える.
[Step6] いざ,XULアプリ
コマンドラインで動くのにXULアプリではコンポーネントが認識されていない場合,compreg.dat, xpti.datが古い可能性がある.XULアプリを実行すると,
Document and setteing/(application.iniで指定されたVendor/Name, randomはランダムな文字列)という個人ディレクトリにもこれら2つのファイルが自動で作られる.コンポーネントを追加した場合はこれらを一旦削除する必要がある.
{user}/Application Data/
{Vendor}/{Name}/Profiles/{random}/
うまく動かない場合は,コマンドラインから -console オプションを付けて実行するとコンソールが現れる.JavaScriptでdump("message")と記述することでコンソールに文字列を出力できるので,実行経路や値の確認に使える.
おまけ
古いcompreg.dat, xpti.datを参照していることはすぐには気づかなかったが,sysinternalsのfilemonを使ってアクセスしたファイルを調べたら,プロファイルディレクトリにも情報が残っているのが見つかった.このツールは行き詰まったときには本当に役に立つ.
Comments