SyntaxHighlighter

ラベル mruby の投稿を表示しています。 すべての投稿を表示
ラベル mruby の投稿を表示しています。 すべての投稿を表示

2012年9月17日月曜日

JsMruby - mruby NPAPI plugin

JsMruby - mruby NPAPI plugin

mruby を Firefox, Google Chrome で動作するようにしました。

mruby

mruby on EFI Shell でも書いたように、 mruby は、Ruby の作者であるまつもとさんが開発されている「組込み向け軽量 Ruby」の実装です。

前回は、単に EFI Shell 上で動くようにコンパイルしただけでしたが、今回は Firefox, Chrome 上から mruby スクリプトを実行でき、 JavaScript の関数も呼べるようにしてみました。

JsMruby - mruby NPAPI plugin

Firefox, Chrome 上で動作する mruby の NPAPI plugin を作ってみました。

サンプル

このプラグインを Firefox, Chrome にインストールしていると、以下のような書き方ができます。

ちょっと長いですが、全文を載せます。

この HTML ファイルを開き、 Draw ボタンをクリックすると、 canvas に正方形が描かれます。

もう少し長いサンプルとしては、マンデルブロ集合を描くサンプルを参照してみてください。
このサンプルでは Draw を押してから 3 秒ぐらい待ってから描画されます。

このように、割とシームレスに JavaScript のメソッドが呼べ、これまで JavaScript で書かねばならなかったものを mruby で書けるようになります。

概要

現在のところ、以下のようなことができます。上のサンプルを参照しながら読んでみてください。
ただし、これらは今後の実装次第で変わっていくだろうと思います。

JavaScript から mruby スクリプトの実行

object タグで NPAPI プラグインを読み込みます。

このオブジェクトに対して、load メソッドで mruby スクリプトをパースし、実行できます。

その後は、 send メソッドで、 mruby スクリプト内で定義したメソッドを直接実行することができます。

mruby から JavaScript スクリプトの実行

逆に mruby スクリプト側からは、 JsObj.get() メソッドで JavaScript のオブジェクトを取得できます。

現在の実装では、 Array, String, Integer, Double などに関しては、 mruby の該当するオブジェクトに変換されます。
また、 DOM オブジェクトなどの場合は、 DOM オブジェクトそのものをラップした JsObj クラスのインスタンスが返され、そのインスタンスに対しては、通常の DOM オブジェクトに対するメソッドを呼び出すことができます。(createElement などを呼べます)
function の場合は、 mruby の Proc オブジェクトのようなものが返されます。(ただし call メソッドでしか呼び出せません)

制限

現在のものは、あくまでアルファ版なのでクラッシュしたりうまく動かなかったりするだろうと思います。

特に、例外まわりやガベージコレクションまわりについては、それほどきちんと考えて書いていないので、不具合が多く眠っているだろうと思います。

ダウンロードとインストール

いずれも GitHub のページからダウンロードできます。

まだ Windows 向けにしか作成していないので、 Mac などでは動きません。

Firefox
jsmruby_0_0_1.xpi をダウンロードし、そのファイルを Firefox に Drag & Drop するとインストールできます。
このアドオンは、単に JsMruby の NPAPI プラグインを含んでいるだけのものです。
余談ですが、 NPAPI プラグインを含むアドオンを作成する場合は、 install.rdf 内に <em:unpack>true</em:unpack> の一行を書く必要があります。
Chrome
jsmruby_0_0_1.zip をダウンロードし、そのファイルをローカルで展開します。
Chrome の「ツール」-「拡張機能」を開いて「デベロッパーモード」にチェックを入れ、「パッケージ化されていない拡張機能を読み込む」から展開したディレクトリを指定して読み込みます。

ソースコードは GitHub の JsMruby のページで見られます。
まだ整理できていないですが、そのうち整理します。
また、 Mozilla のサンプルソースを使っている関係上、一部のファイルのみ NPL ですが、それ以外のファイルに関しては MIT ライセンスとする予定です。

ブラウザ上の Ruby

既に本家の Ruby では、 Ruby 2.0 にて Chrome の NaCl に対応することが表明されています。
似たようなのを作っておいて書くのも何ですが、私はこちらにとても期待しています。

また、 mruby についても既に試されている方がいらっしゃいます。

私はまだそれほど NaCl や PPAPI については勉強していないのと、 Chrome よりも Firefox が好きなので Firefox で動かしたい、という動機があったので、この NPAPI 版のプラグインを作ってみました。
というか、 masuidrive さんの MobiRuby の講演を聞いて、「いいなぁ」と思って自分も何か作りたくなったというのが本音です。

EFI Shell 版の方は、使いたい人はあまりいないと思いますが、 Windows 8 リリースまでにはまとめようかと思っています。

暇を見つけて Mac 版や、ドキュメントの作成などをします。たぶん。

2012年5月21日月曜日

mruby on EFI Shell

mruby on EFI Shell

mruby を 32bit, 64bit の EFI Shell 上で動かしてみました。

mruby

mruby は、Ruby の作者であるまつもとさんが開発されている「組込み向け軽量 Ruby」の実装です。

詳しくは ITPro の紹介記事などをご覧ください。

今回は、この mruby を EFI Shell 上で動かしてみました。

EFI と EFI Shell

EFI

EFI もしくは UEFI とは、BIOS の置き換えのために Intel などが中心となって策定したファームウェアの仕様です。

最近の PC はほぼ UEFI 対応していますが、だからといって、すべてのもので EFI Shell が立ち上げられるとは限りません。
また、UEFI Boot 自体も、まだそれほど一般的ではないかもしれません。
ベンダによっては、UEFI なのに、UEFI Native Boot ではなく Legacy Boot させている (つまり CSM Boot させている) ところも多いようです。

ただし、Windows 8 が出てくるころには、状況も変わってくると思います。

EFI Shell

詳しく書くときりがないので EFI の詳細については省略しますが、その仕様の中で、EFI Shell という DOS や bash のようなシェル環境が定義されており、実際にいくつかの UEFI Boot 対応 PC では、Firmware 内に組込まれています。

BIOS Setup 画面で Launch EFI Shell のような項目があれば、それが該当します。
また、EFI Shell バイナリを USB メモリなどから起動させることで起動することもできます。

で、今回、この EFI Shell 上で動くように mruby をコンパイルしてみました。

動作例とダウンロード

ダウンロードは GitHub から可能です。
展開して得られるバイナリのうち、mruby.efi は 32bit 用、mruby64.efi は 64bit 用です。

VMware Player 上で動かすと、以下のようになります。
図は [ 10, 2, 4, 1 ].sort.each{ |i| p i } を引数で直接指定して実行したところです。
ファイルを渡してももちろん動作します。

作業記録とソースコード

以下は、作業記録です。

ソースコード

EFI Shell アプリケーションを作るので、EDK と mruby の二つが必要です。

EDK は edk2_for_mruby として、 mruby は mruby_efi_shell として、どちらも GitHub 上に置いてあります。

まず、edk2_for_mruby をダウンロードして展開し、続いて AppPkg/Applications/mruby に mruby_efi_shell を展開します。
やったことがなかったので、サブモジュールなどの設定はまだしていません。

ビルド環境

少し古いですが、現在の Mac や Let's note を使い始める前に使っていた Ubuntu 9.10 (Karmic Koala) でビルドしました。
ただし、これはすでにサポート期限が切れているので、これから始める人は、12.X をインストールした方がよいでしょう。
(余談ですが、私の実機では、 12.X をインストールすると、画面の Refresh Rate がおかしくなったので、面倒になってインストールをやめました。)

また、32bit, 64bit いずれの mruby.efi をビルドする場合でも、32bit の Ubuntu で可能です。
ただし、64bit 版を試すには、VMware Player で 64bit の EFI をエミュレートできる必要があります。
よく分かっていませんが、64bit CPU を搭載している必要があるだろうと思います。また、 Intel-VT などが有効になっている必要があるかもしれません。

あとは、EDK の How to build を見ながら設定していきます。
Unix-like systems でのビルド方法にも、必要なライブラリ (build-essential など) が書かれているので、入れていなかったらインストールします。

ソースの変更

ビルドするために、いくつか変更を加えました。

詳しくは GitHub の履歴を見ていただければいいですが、悩んだのは EDK 側のバグでした。

EFI Application で C の標準ライブラリを使えるようにするためのラッパが用意されているのですが、その中の一つである StdLib/LibC/Main/Main.cmain 関数の宣言が間違っていました。

正確には、それを呼び出しているサンプルである AppPkg/Applications/Main/Main.c との整合性がとれておらず、呼び出し規約が異なったものになっていました。

そのため、偶然、32bit 環境では動作するのに、64bit では動作せず、かなり悩むはめになりました。

それ以外は、y.tab.c のように動的に生成されるものをいくつかあらかじめ作っておくなどをしました。

なお、EDK 側に関数が定義されていないものがあり、現状は math モジュールは除いてあります
今後、必要なら EDK 側に実装するなどして、対応しようと思います。

テスト環境

テスト環境には VirtualBoxVMware Player を用いました。

VirtualBox では、「システム」の「EFI を有効化」にチェックをすることで、Bootable Device がなければ、32bit の EFI Shell が自動で立ち上がります。

VMware Player では、*.vmx ファイルに、以下の行を加えることで EFI Boot させることができます。
efi は小文字にする必要があります。

firmware = "efi"

これで、 Bootable Device がなければ、EFI Shell が自動で立ち上がるはずです。
なお、私の環境では Network の部分でハングしていたので、 Network デバイスを削除しておきました。

以上で 32bit, 64bit ともにテストができるはずです。

今後

今後は、EFI の機能を簡単に呼べるようなライブラリを作っておこうと思います。

少なくとも、Boot Service, Runtime Service ぐらいは Ruby の関数として提供しようと思います。

可能なら、すでに EDK に入っている Python のように、mruby を EDK に含めてもらいたいです。