Home > Latest topics

Latest topics > XUL/MigemoのXPCOMコンポーネント化

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

XUL/MigemoのXPCOMコンポーネント化 - Mar 10, 2007

JavaScriptによるXPCOMコンポーネント作成の練習に、XUL/Migemo勝手改造版の主要な部分をXPCOMコンポーネントにするという実験をやってみた。

ブランチ切って昨日一日作業してたんだけど、それなりにうまくいったようなので、すでにTrunkにマージはしてある(Subversionでブランチ切ったものを再び統合するやり方が分からなくて右往左往したのは秘密だ)。

そんなことをしてどんな意味があるのかっていうとまあほとんど意味なんか無いんだけど、強いてメリットを挙げれば以下のような感じ?

  • 普通に作るとウィンドウごとにスクリプトが読み込まれるので、辞書やキャッシュをウィンドウ間で同期させるのが面倒。XPCOMコンポーネントにしてしまえば、Firefoxが動作している間は単一のオブジェクトを各ウィンドウから参照できる。
  • 機能を使うときに、いちいちスクリプトをscriptタグで読み込ませなくても、var XMigemoFind = Components.classes['@piro.sakura.ne.jp/xmigemo/find;1'].createInstance(Components.interfaces.pIXMigemoFind);と書くだけで辞書の初期化まで含めて全部完了できるようになった。
  • スクリプトを書くときに、グローバル変数を気楽に使えるので、場合によってはラクに書けるようになる。

デメリットというか、XPCOMコンポーネントにする場合に制限があることも分かった。と思う。

  • 配列や正規表現オブジェクトなど、JavaScriptの組み込みオブジェクトをそのまんま返すような機能は作れない(みたい)。配列を返そうと思ったら、nsISimpleEnumeratorの形に変換するようなwrapperをかまさないといけない。
  • ウィンドウに依存しない代わりに、ウィンドウを参照できないので、window.setTimeoutなども使えない。タイマー処理を使いたい場合は、代わりにnsITimerを使う必要がある。
  • IDLでインターフェースの定義を書くとき、返り値の型を間違えると文字化けしたりする。Unicode文字列はとりあえずwstringでいいようだけど、それ以外のの使い分けが分からない……JavaScriptには「文字列」と「整数値」と「真偽値」と「オブジェクト」しかないから、数値だけでなんでこんなにたくさん型があるのかサッパリ分からない。
  • JavaScriptだと関数の引数を省略してもちゃんと動くけど、XPCOMコンポーネントにすると、「引数が足らねえぞゴラァ」というエラーになってしまう。なので、利用する時に若干面倒になる。

Firefoxのソース(特にFx 2のセッションマネージャなど)を見ながら試行錯誤でどうにかここまで。

しかしまあこんな事覚えても、Fx(とかThunderbirdとかあたり)以外では全然役に立たない知識だよなあ……ますます無駄にニッチな方向にばかり突き進んでる気がする。

分類:Mozilla > XUL, , , , , , , 時刻:02:14 | Comments/Trackbacks (2) | Edit

Comments/Trackbacks

JSでのXPCOMコンポーネント作成

インターフェースとコンポーネントが一対一に対応するとは限らないので、インターフェースのUUID (IID)とコンポーネントのUUID (ClassID)は別のものを使う必要があると思います。

また、コンポーネントの初回登録時にNS_ERROR_FACTORY_REGISTER_AGAINを投げる必要はないかもしれません。
https://bugzilla.mozilla.org/show_bug.cgi?id=253125

ちなみに、配列を返すのは以下でできます。

/* IDL */
void getArray(out unsigned long aCount,
[array, size_is(aCount), retval] out long aArray);

/* JS (実装) */
getArray: function getArray(aCount) {
var array = [10, 20, 30];
aCount.value = array.length;
return array;
},

/* JS (呼び出し) */
var array = component.getArray({});

それから、文字列型についてはwstring型ではなくAString型を使ったほうがいい気がします(NUL文字を含むことができ、バッファ共有でメモリ効率もいい場合あり?)。浮動小数点数型に関しても、floatだと精度が落ちるかもしれないのでdoubleのほうがいいかと思います。
http://developer.mozilla.org/en/docs/XPCOM_string_guide

なお、コンポーネントが常にJavaScriptから呼び出されるのならば、以下のようにして可変長引数を実現可能です。

/* IDL */
long sum();

/* JS (実装) */
sum: function sum() {
// 適宜引数をチェックしてNS_ERROR_INVALID_ARGを投げるなど
var result = 0;
args = arguments.callee.caller.arguments;
for (var i = 0; i < args.length; i++)
result += args[i];
return result;
},

/* JS (呼び出し) */
var sum = component.sum(1, 2, 3, 4);

Commented by nanto_vi at 2007/03/10 (Sat) 07:30:34

no title

うおおお
JavaScriptの偉い人にツッコミをいただいてしまった!
スミマセンいいかげんな知識であれこれ書いてしまっておりました……数年前にTips全消しした時の教訓がまるで活かされておりませんね、と一部の人にしか分からない話をしてみる。

配列を返す処理についてはさっそく導入させていただきました。正規表現を引数に渡せない所ばっかりはどうしようもないのかなという感じですが、今までのAPIとの互換性が若干高まったので僕としてはわりと満足いく結果となっています。
呼び出し元は現実的にはまあXUL/Migemo [Forked Edition]のフロントエンドしか無いと思われるので、お教えいただいた方法もいいかなと思うんですが、なんとなく気持ち悪い感覚が拭えないので、見送ることにします。

AStringをwstringの件なんですが、試しながら置き換えていってみた所だいたいの部分はAStringで問題ないことが分かったので、早速そのようにしました。こないだ試した時に上手くいかなかったのは、どうもAStringと書くべき所を間違えてACStringと書いてしまっていたからのようです(というか、AStringとACStringの違いが分かってなかった)。

Commented by Piro at 2007/03/12 (Mon) 04:38:06

TrackBack ping me at


の末尾に2020年11月30日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2007-03-10_xulmigemo-xpcom.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2020年11月30日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき