mruby/edgeの進捗ブログです。
mruby/edgeとは、という話はここです:
もっと聞きたい人は5月に沖縄にいくといいらしい。
wasmバイナリの中身を軽く話す話
wasmバイナリにどんなセクションがあるか、とか、使い方とは、みたいな話は以下の本をサクッと読んでください。ちなみに Component Model以前の内容ではありますが、今ある日本語の本の中で一番いい感じにカバーしてると思う。
その上でwasmバイナリは関数をexportできます(普通のshared objectみたい)。 wasm-objdump
というコマンド(from wabt)を使えます。
$ wasm-objdump -x -j Export hello.wasm hello.wasm: file format wasm 0x1 module name: <mywasm.wasm> Section Details: Export[2]: - memory[0] -> "memory" - func[395] <hello.command_export> -> "hello"
この "hello"
を呼び出すには例えば wasmedge を使って以下のようにします。
$ wasmedge --reactor hello.wasm hello My own wasm Nil
ブラウザでのJavaScriptでもこのexportという概念は大事で、以下のようなコードで呼び出す使い方が基本かなと思います。 ref MDN
WebAssembly.instantiateStreaming(fetch("hello.wasm"), importObject).then( (obj) => obj.instance.exports.hello(), );
また、例えば proxy-wasm のような用途では、特定の関数を export したwasmバイナリ(ABIに沿ったバイナリ)を作って読み込ませる運用を想定しています。
なのでwasmをコンパイルするにあたって、どの関数をどういう定義でexportするかというのは非常に大事です。
mruby/edgeではこうしました
ということで、mruby/edgeではこういうRubyスクリプト fib.rb
があるときに
def fib(n) if n < 2 return 1 else return fib(n-1) + fib(n-2) end end
fib
というトップレベルのメソッドをそのまま関数としてexportしたいなと思いました。
どういう関数があるねというのを検知させてもいいんですが、逆に無闇に複雑な実装になるかなと思い、以下のような内容の fib.export.rbs
を用意させることにしました。
def fib: (Integer) -> Integer
fib.rb
と fib.export.rbs
が同じディレクトリにある時、 mec
コマンド v0.2.0 を叩くと:
$ cargo install --version 0.2.0 mec $ mec fib.rb ... [ok] wasm file is generated: fib.wasm
$ wasm-objdump -x -j Export fib.wasm fib.wasm: file format wasm 0x1 module name: <mywasm.wasm> Section Details: Export[3]: - memory[0] -> "memory" - func[397] <fib.command_export> -> "fib"
と言いつつ、今までは --fnname
で指定していました。進歩した点としてはシグネチャもこれで指定可能になっています。FunctionとTypeセクションを見比べることで、 fib
がちゃんと (i32) -> i32
の関数として定義されていることがわかる。
$ wasm-objdump -x -j Function fib.wasm | grep 'fib' fib.wasm: file format wasm 0x1 - func[16] sig=2 <fib> - func[397] sig=2 <fib.command_export> $ wasm-objdump -x -j Type fib.wasm | grep 'type\[2\]' - type[2] (i32) -> i32
呼び出すとこうなります。もちろんブラウザでも使えます、はず。
$ wasmedge --reactor fib.wasm fib 12 233
ちなみに今回の対応で複数の関数をexportすることも可能になりました。
def fib: (Integer) -> Integer def hello: () -> void
$ wasm-objdump -x -j Export fib.wasm fib.wasm: file format wasm 0x1 module name: <mywasm.wasm> Section Details: Export[3]: - memory[0] -> "memory" - func[397] <fib.command_export> -> "fib" - func[398] <hello.command_export> -> "hello"
まだちゃんと動かない(例えばいわゆる文字列の扱いをどうするかとか)点もありますが、そこはwasmに詳しくなって頑張る...。
今回の対応は、 RBS 勢的にもやや興味深い使い方なのかも? と思ったりしています(率直な意見を沖縄などで聞きたい)。
肝心の mruby/edgeコアは相変わらず基本的な命令もまだまだですが、とは言えやるだけのことなので...粛々やる...