From ef3e6af4da82189512c6b5a705b63fca5efce99e Mon Sep 17 00:00:00 2001 From: Yuji Sugiura Date: Sun, 19 Jul 2020 11:42:52 +0900 Subject: [PATCH] Translate wasm-2 into Japanese --- wasm/ja/chapter_2.yaml | 207 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 wasm/ja/chapter_2.yaml diff --git a/wasm/ja/chapter_2.yaml b/wasm/ja/chapter_2.yaml new file mode 100644 index 000000000..a6c1406fe --- /dev/null +++ b/wasm/ja/chapter_2.yaml @@ -0,0 +1,207 @@ +- title: 2章 - データ構造を共有する + content_markdown: > + JavaScriptとWebAssemblyのプログラムでは、メモリ上でのデータの表現が大きく異なります。 + + そしてより複雑なことに、WebAssemblyからホスト環境への干渉は厳しく制限されています。 + + + この章では、そんな中でも互いにデータをやり取りするための方法を探ります。 +- title: 関数のインポート + code: 'https://webassembly.studio/?embed&f=pp20eedhka' + content_markdown: > + WebAssemblyのモジュールでは、明示的にインポートされた関数しか呼ぶことができません。 + + + Rustのコードでは、`extern "C" { ... }`と記述することで、インポートしている関数を列挙できます。 + + + インポートされた関数について、Rustコンパイラはその実装を知らないため、動作保証ができません。 + そのため、`unsafe`なものとして扱われることに注意してください。 +- title: 関数の制限 + content_markdown: > + 関数から返すことのできる値は、次のものに限られます。 + + + * i32/i64 + + * f32/f64 + + + そのため、JavaScriptとWebAssembly間のデータのやり取りのためには、数値の意味についてより深く知らねばなりません。 + + + Rustでプリミティブな数値型を返すと、それはうまくWebAssemblyの数値表現に変換されます。 +- title: メモリのエクスポート + content_markdown: > + WebAssemblyのプログラムは、メモリ領域を最大4GBまでのバイト列としてエクスポートできます。 + + + そしてホスト側で、そのデータ構造を解釈することができます。 + + また、このバイト列は、ホスト側からも直接書き込むこともできます。 + + + WebAssemblyのメモリから読み込む、または書き込むことが、プリミティブではない値のやりとりのための手段というわけです。 +- title: ArrayBuffer + content_markdown: | + JavaScrtipでは、バイト列を`ArrayBuffer`として表現します。 + + そこから任意の型のビューを取得して、操作することができます。 + + ```JavaScript + // 8バイトの領域を初期化 + let bytes = new ArrayBuffer(8); + + // 8ビット符号なし整数としてビューを取得 + let u8_bytes = new Uint8Array(bytes); + // ArrayBufferを操作 + u8_bytes[0] = 16; // 00010000 + u8_bytes[1] = 1; // 00000001 + + // 32ビット符号あり整数のビューとして改めて変換 + let i32_bytes = new Int32Array(u8_bytes.buffer); + console.log(i32_bytes[0]); + ///272 or 00010000000000010000000000000000 + ``` +- title: UTF-8エンコード/デコード + content_markdown: > + JavaScriptには、UTF-8の文字列を、`ArrayBuffer`内に書き込む、読み出すための便利な関数があります。 + + + ```JavaScript + + let bytes = new ArrayBuffer(8); + + const data = new Uint8Array(bytes); + + data[0] = 72; // H + + data[1] = 105; // i + + data[2] = 33; // ! + + let str_len = 3; + + const utf8dec = new TextDecoder("utf-8"); + + // subarrayはその範囲をインデックス指定する + + let text = utf8dec.decode(data.subarray(0,str_len)); + + console.log(text) // Hi! + + const utf8enc = new TextEncoder("utf-8"); + + let text_bytes = utf8enc.encode(text); + + console.log(text_bytes) + + // Uint8Array(3) [72, 105, 33] + + ``` +- title: テキストのロギング + code: 'https://webassembly.studio/?embed&f=1gxcr004p3x' + content_markdown: > + WebAssemblyのプログラムから、テキストをロギングする簡単な例を見てみましょう。 + + + 次のような流れになります。 + + 1. プログラムのメモリから、utf-8のテキストをつくる + + 2. そのテキストの長さを判断する + + 3. そのテキストが格納されているスタート位置と長さをホストのブラウザ側に伝え、`console.log`を実行 + + + これはJavaScript側の関数をどのように実装するかの例です。 + + + ```JavaScript + + wasm_log(start,len) { + // 開始位置と長さから、テキストを抽出する + const utf8dec = new TextDecoder("utf-8"); + let buffer = module.instance.exports.memory.buffer; + let memory = new Uint8Array(buffer); + let text = utf8dec.decode(memory.subarray(start,start+len)); + console.log(text); + } + + ``` +- title: テキストの読み込み + code: 'https://webassembly.studio/?embed&f=ubmxmavgf2' + content_markdown: > + 次は、その反対の考え方をしてみます。WebAssemblyのプログラムに、テキストを渡したい場合です。 + + + 次のような流れになります。 + + 1. 渡したいテキスト(バイト列)の長さを求める + + 2. その長さの分だけメモリを確保する + + 3. 開始位置を指定して、確保したメモリにバイト列をコピー + + 4. WebAssemblyのプログラムに、特定の位置と長さでデータを渡したことを知らせる + + + これがその初期化の例です。 + + + ```JavaScript + + // 文字列"Ferris"をバイト列に + + const utf8enc = new TextEncoder("utf-8"); + + let text = "Ferris"; + + let text_bytes = utf8enc.encode(text); + + + // そのための領域を確保 + + let len = text_bytes.length; + + let start = module.instance.exports.wasm_malloc(len); + + + // WebAssemblyのメモリに配置 + + let buffer = module.instance.exports.memory.buffer; + + let memory = new Uint8Array(buffer); + + memory.set(text_bytes, start); + + + // プログラムを実行 + + module.instance.exports.main(start,len); + + ``` +- title: 表現を見つける + content_markdown: > + テキストの開始位置や長さを渡すことに煩雑さを覚えるかもしれません。 + + + これは、C言語で文字列の終端を表すのに`\0`を使っていたようなものだと考えてください。 + + + データ構造をいちいちバイトに包んで渡したくない場合は、JSON形式で渡すことも検討してください。 + + + どのようにそれを表現するかはあなた次第ですし、ユースケースに応じて使い分けるようにしてください! +- title: 2章のまとめ + content_markdown: > + ホスト側とWebAssemblyのプログラムの間をまたぐのは面倒ですが、それにより多くのことを得られます。 + + + WebAssemblyは、JavaScriptよりも細かなメモリ構造に関心のある、ローレベルな実行環境であることを忘れないことが重要です。 + + あわせて、これらをより簡単に行うためのライブラリがあることも確認してください。 + Rustの場合、[wasm-bindgen](https://github.com/rustwasm/wasm-bindgen)が人気の選択肢です。 + + + 次の章では、動的にJavaScriptの関数を呼び出す方法と、ガベージコレクションについて見ていきます。