diff --git a/files/ja/webassembly/c_to_wasm/index.html b/files/ja/webassembly/c_to_wasm/index.html deleted file mode 100644 index d1f297e6b23499..00000000000000 --- a/files/ja/webassembly/c_to_wasm/index.html +++ /dev/null @@ -1,177 +0,0 @@ ---- -title: C/C++からWebAssemblyにコンパイルする -slug: WebAssembly/C_to_wasm -translation_of: WebAssembly/C_to_wasm ---- -
{{WebAssemblySidebar}}
- -

C / C ++のような言語でコードを書いたら、Emscripten のようなツールを使って WebAssembly にコンパイルすることができます。 どのように動作するかを見てみましょう。

- -

Emscripten の環境設定

- -

まず、必要な開発環境をセットアップしましょう。

- -

準備

- -

Emscripten SDKを取得します。以下の指示にしたがってください。https://emscripten.org/docs/getting_started/downloads.html

- -

サンプルコードをコンパイルする

- -

環境を設定した後は、C のサンプルコードを Emscripten にコンパイルする方法を見てみましょう。 Emscripten でコンパイルするときにはいくつかのオプションがありますが、この記事でカバーする主な2つのシナリオは次のとおりです:

- - - -

2つについて見てみましょう。

- -

HTML と JavaScript を生成する

- -

最も簡単なケースを見てみましょう。コードを WebAssembly としてブラウザで実行するための全てを Emscripten で生成するようにします。

- -
    -
  1. まずはコンパイルするためのサンプルコードを用意します。以下のCのサンプルコードをコピーして hello.c としてローカルドライブの新しいディレクトリに保存してください: - -
    #include <stdio.h>
    -
    -int main(int argc, char ** argv) {
    -  printf("Hello World\n");
    -}
    -
  2. -
  3. Emscripten コンパイラ環境を導入したターミナルウィンドウを使用して、hello.c ファイルと同じディレクトリに移動して、次のコマンドを実行します: -
    emcc hello.c -s WASM=1 -o hello.html
    -
  4. -
- -

このコマンドで渡されたオプションは次のとおりです:

- - - -

この時点でソースディレクトリに以下のファイルが出力されているはずです:

- - - -

サンプルコードを実行する

- -

WebAssembly をサポートしているブラウザで hello.html をロードするだけです。WebAssembly は Firefox 52+ と Chrome 57+/最新の Opera でデフォルトで有効になっています (Firefox 47+では about:configjavascript.options.wasm flag を有効にすることで、Chrome (51+) と Opera (38+) では chrome://flags に飛んで Experimental WebAssembly フラグを有効にすることで wasm コードを実行することができます) 。

- -

全てが計画通りに機能していれば、ウェブページ上の Emscripten コンソールに "Hello world" の出力が表示されるはずです。おめでとうございます、ようやくCを WebAssembly にコンパイルしてブラウザで実行することができました!

- -

カスタム HTML テンプレートを使う

- -

場合によっては、カスタム HTML テンプレートを使用することもできます。 どうやってできるかを見てみましょう。

- -
    -
  1. -

    まず、次の C のコードを hello2.c として新しいディレクトリに保存します:

    - -
    #include <stdio.h>
    -
    -int main(int argc, char ** argv) {
    -    printf("Hello World\n");
    -
    -}
    -
  2. -
  3. -

    shell_minimal.html をあなたの emsdk レポジトリから探します。先程作成した新しいディレクトリに html_template というサブディレクトリを作って、そこにコピーします。

    -
  4. -
  5. -

    新しいディレクトリに移動して (Emscripten コンパイラ環境があるターミナルウィンドウで) 、次のコマンドを実行します:

    - -
    emcc -o hello2.html hello2.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html
    - -

    今回渡したオプションは少しだけ異なります:

    - - -
  6. -
  7. -

    この例を実行してみましょう。上記のコマンドで hello2.html が生成されます。これは生成された wasm コードに対してロード、実行などを行うグルーコードを含むテンプレートと同じ内容を持ちます。ブラウザを開いて最後の例と同じ出力であることを確認してください。

    -
  8. -
- -
-

: 例えば、 emcc -o hello2.js hello2.c -O3 -s WASM=1 のように -o フラグにHTMLファイルの代わりに .js ファイルを渡すことで JavaScript で出力することを指定できます。そのあとに、スクラッチで独自のカスタム HTML を作ることができます。しかし、これはおすすめできません — Emscripten はメモリ割り当て、メモリリークやその他の問題を扱うための JavaScript グルーコードが多数必要になります。これは提供されたテンプレートにすでに含まれています。全てをあなた自身で書くよりも簡単に使用できます。していること全てに習熟してきたら、必要に応じて独自のカスタマイズバージョンを作りましょう。

-
- -

C で定義されたカスタム関数を呼び出す

- -

C で定義された関数があって、それを JavaScript から呼び出したい場合、Emscripten の ccall() 関数と EMSCRIPTEN_KEEPALIVE 宣言 (対象の関数をエクスポートする関数リストに加えるものです (Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process? を参照してください)) を使用します。これがどのように働くか見てみましょう。

- -
    -
  1. -

    はじめに、次のコードを hello3.c として新しいディレクトリに保存します:

    - -
    #include <stdio.h>
    -#include <emscripten/emscripten.h>
    -
    -int main(int argc, char ** argv) {
    -    printf("Hello World\n");
    -}
    -
    -#ifdef __cplusplus
    -extern "C" {
    -#endif
    -
    -void EMSCRIPTEN_KEEPALIVE myFunction(int argc, char ** argv) {
    -  printf("MyFunction Called\n");
    -}
    -
    -#ifdef __cplusplus
    -}
    -#endif
    - -

    デフォルトでは、Emscripten が生成したコードは常に main() を呼び出し、他のデッドコードは削除されます。関数名の前に EMSCRIPTEN_KEEPALIVE を置くことによって、これが起こらなくなります。また、EMSCRIPTEN_KEEPALIVE を使用するために emscripten.h をインポートする必要があります。

    - -
    -

    : #ifdef ブロックを加えたことによって、C++ のコードからこの例をインクルードしようとしても動作するでしょう。 C と C++ の間でのマングリング規則によって、他の場合では壊れることもありますが、ここでは C++ を使用している場合に、外部の C の関数として扱うように設定しています。

    -
    -
  2. -
  3. -

    便宜上、この新しいディレクトリに html_template/shell_minimal.html (もちろん、このファイルはあなたの実際の開発環境に置きます)を加えます。

    -
  4. -
  5. -

    さて、再びコンパイル手順を実行しましょう。あなたの最新のディレクトリの中 (そして、Emscripten コンパイラ環境の入っているターミナルウィンドウ) で、このように C のコードをコンパイルします (NO_EXIT_RUNTIMEオプションを付与してコンパイルする必要があることに注意してください。そうしない場合、 main() 関数が終了したときにランタイムもシャットダウンされてしまい、コンパイルされたコードが正しく呼ばれなくなる可能性があります - 例えば、atexitの呼び出しなどの適切なCのエミュレーションに必要です):

    - -
    emcc -o hello3.html hello3.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']"
    -
  6. -
  7. -

    例をブラウザでロードしたら、前と同じものが見られるでしょう。

    -
  8. -
  9. -

    JavaScript から新しい myFunction() 関数を呼び出す必要があります。まずは、 以下のような{{htmlelement("button")}} を最初の <script type='text/javascript'> タグの上に加えましょう。

    - -
    <button class="mybutton">Run myFunction</button>
    -
  10. -
  11. -

    そして、{{htmlelement("script")}} 要素内の最後に次のコードを追加します ( </script> タグの直前):

    - -
    document.querySelector('.mybutton').addEventListener('click', function(){
    -  alert('check console');
    -  var result = Module.ccall('myFunction', // name of C function
    -                             null, // return type
    -                             null, // argument types
    -                             null); // arguments
    -});
    -
  12. -
- -

これはエクスポートされた関数をどのようにして ccall() を使用して呼び出すかを示しています。

- -

関連情報

- - diff --git a/files/ja/webassembly/c_to_wasm/index.md b/files/ja/webassembly/c_to_wasm/index.md new file mode 100644 index 00000000000000..0bd517c7337c8f --- /dev/null +++ b/files/ja/webassembly/c_to_wasm/index.md @@ -0,0 +1,158 @@ +--- +title: C/C++からWebAssemblyにコンパイルする +slug: WebAssembly/C_to_wasm +translation_of: WebAssembly/C_to_wasm +--- +{{WebAssemblySidebar}} + +C / C ++のような言語でコードを書いたら、[Emscripten](/ja/docs/Mozilla/Projects/Emscripten) のようなツールを使って WebAssembly にコンパイルすることができます。 どのように動作するかを見てみましょう。 + +## Emscripten の環境設定 + +まず、必要な開発環境をセットアップしましょう。 + +### 準備 + +Emscripten SDK を取得します。以下の指示にしたがってください。 + +## サンプルコードをコンパイルする + +環境を設定した後は、C のサンプルコードを Emscripten にコンパイルする方法を見てみましょう。 Emscripten でコンパイルするときにはいくつかのオプションがありますが、この記事でカバーする主な 2 つのシナリオは次のとおりです: + +- wasm にコンパイルし、コードを実行するための HTML とウェブ環境上で wasm を実行するための全ての JavaScript グルーコードを生成する。 +- wasm にコンパイルと JavaScript の生成だけ行う。 + +2 つについて見てみましょう。 + +### HTML と JavaScript を生成する + +最も簡単なケースを見てみましょう。コードを WebAssembly としてブラウザで実行するための全てを Emscripten で生成するようにします。 + +1. まずはコンパイルするためのサンプルコードを用意します。以下の C のサンプルコードをコピーして `hello.c` としてローカルドライブの新しいディレクトリに保存してください: + + ```cpp + #include + + int main(int argc, char ** argv) { + printf("Hello World\n"); + } + ``` + +2. Emscripten コンパイラ環境を導入したターミナルウィンドウを使用して、`hello.c` ファイルと同じディレクトリに移動して、次のコマンドを実行します: + + ```bash + emcc hello.c -s WASM=1 -o hello.html + ``` + +このコマンドで渡されたオプションは次のとおりです: + +- `-s WASM=1` — 出力を wasm に指定します。指定しない場合、Emscripten はデフォルトでは [asm.js](http://asmjs.org/) として出力します。 +- `-o hello.html` — コードを実行するための HTML ページを指定します。wasm モジュールとそれをウェブ環境で使用できるようにコンパイル、インスタンス化するための JavaScript グルーコードも出力に含まれます。 + +この時点でソースディレクトリに以下のファイルが出力されているはずです: + +- バイナリの wasm モジュールコード (`hello.wasm`) +- ネイティブの C の関数と JavaScript/wasm の間で変換を行う JavaScript ファイル (`hello.js`) +- wasm コードをロード、コンパイル、インスタンス化し、ブラウザに出力するための HTML ファイル (`hello.html`) + +### サンプルコードを実行する + +WebAssembly をサポートしているブラウザで `hello.html` をロードするだけです。WebAssembly は Firefox 52+ と Chrome 57+/最新の Opera でデフォルトで有効になっています (Firefox 47+では _about:config_ で `javascript.options.wasm` flag を有効にすることで、Chrome (51+) と Opera (38+) では _chrome://flags_ に飛んで _Experimental WebAssembly_ フラグを有効にすることで wasm コードを実行することができます) 。 + +全てが計画通りに機能していれば、ウェブページ上の Emscripten コンソールに "Hello world" の出力が表示されるはずです。おめでとうございます、ようやく C を WebAssembly にコンパイルしてブラウザで実行することができました! + +### カスタム HTML テンプレートを使う + +場合によっては、カスタム HTML テンプレートを使用することもできます。 どうやってできるかを見てみましょう。 + +1. まず、次の C のコードを `hello2.c` として新しいディレクトリに保存します: + + ```cpp + #include + + int main(int argc, char ** argv) { + printf("Hello World\n"); + + } + ``` + +2. `shell_minimal.html` をあなたの emsdk レポジトリから探します。先程作成した新しいディレクトリに `html_template` というサブディレクトリを作って、そこにコピーします。 +3. 新しいディレクトリに移動して (Emscripten コンパイラ環境があるターミナルウィンドウで) 、次のコマンドを実行します: + + ```bash + emcc -o hello2.html hello2.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html + ``` + + 今回渡したオプションは少しだけ異なります: + + - `-o hello2.html` と指定したことで、今回コンパイラは JavaScript グルーコードと `.html` を出力します。 + - さらに `--shell-file html_template/shell_minimal.html` と指定しました — これは例を実行する HTML を生成するための、HTML テンプレートパスです。 + +4. この例を実行してみましょう。上記のコマンドで hello2.html が生成されます。これは生成された wasm コードに対してロード、実行などを行うグルーコードを含むテンプレートと同じ内容を持ちます。ブラウザを開いて最後の例と同じ出力であることを確認してください。 + +> **Note:** **注**: 例えば、 `emcc -o hello2.js hello2.c -O3 -s WASM=1` のように `-o` フラグに HTML ファイルの代わりに .js ファイルを渡すことで JavaScript で出力することを指定できます。そのあとに、スクラッチで独自のカスタム HTML を作ることができます。しかし、これはおすすめできません — Emscripten はメモリ割り当て、メモリリークやその他の問題を扱うための JavaScript グルーコードが多数必要になります。これは提供されたテンプレートにすでに含まれています。全てをあなた自身で書くよりも簡単に使用できます。していること全てに習熟してきたら、必要に応じて独自のカスタマイズバージョンを作りましょう。 + +### C で定義されたカスタム関数を呼び出す + +C で定義された関数があって、それを JavaScript から呼び出したい場合、Emscripten の `ccall()` 関数と `EMSCRIPTEN_KEEPALIVE` 宣言 (対象の関数をエクスポートする関数リストに加えるものです ([Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process?](https://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html#why-do-functions-in-my-c-c-source-code-vanish-when-i-compile-to-javascript-and-or-i-get-no-functions-to-process) を参照してください)) を使用します。これがどのように働くか見てみましょう。 + +1. はじめに、次のコードを `hello3.c` として新しいディレクトリに保存します: + + ```cpp + #include + #include + + int main(int argc, char ** argv) { + printf("Hello World\n"); + } + + #ifdef __cplusplus + extern "C" { + #endif + + void EMSCRIPTEN_KEEPALIVE myFunction(int argc, char ** argv) { + printf("MyFunction Called\n"); + } + + #ifdef __cplusplus + } + #endif + ``` + + デフォルトでは、Emscripten が生成したコードは常に `main()` を呼び出し、他のデッドコードは削除されます。関数名の前に `EMSCRIPTEN_KEEPALIVE` を置くことによって、これが起こらなくなります。また、`EMSCRIPTEN_KEEPALIVE` を使用するために `emscripten.h` をインポートする必要があります。 + + > **Note:** **注**: `#ifdef` ブロックを加えたことによって、C++ のコードからこの例をインクルードしようとしても動作するでしょう。 C と C++ の間でのマングリング規則によって、他の場合では壊れることもありますが、ここでは C++ を使用している場合に、外部の C の関数として扱うように設定しています。 + +2. 便宜上、この新しいディレクトリに `html_template/shell_minimal.html` (もちろん、このファイルはあなたの実際の開発環境に置きます)を加えます。 +3. さて、再びコンパイル手順を実行しましょう。あなたの最新のディレクトリの中 (そして、Emscripten コンパイラ環境の入っているターミナルウィンドウ) で、このように C のコードをコンパイルします (NO_EXIT_RUNTIME オプションを付与してコンパイルする必要があることに注意してください。そうしない場合、 main() 関数が終了したときにランタイムもシャットダウンされてしまい、コンパイルされたコードが正しく呼ばれなくなる可能性があります - 例えば、atexit の呼び出しなどの適切な C のエミュレーションに必要です): + + ```bash + emcc -o hello3.html hello3.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']" + ``` + +4. 例をブラウザでロードしたら、前と同じものが見られるでしょう。 +5. JavaScript から新しい `myFunction()` 関数を呼び出す必要があります。まずは、 以下のような{{htmlelement("button")}} を最初の `` タグの直前): + + ```js + document.querySelector('.mybutton').addEventListener('click', function(){ + alert('check console'); + var result = Module.ccall('myFunction', // name of C function + null, // return type + null, // argument types + null); // arguments + }); + ``` + +これはエクスポートされた関数をどのようにして `ccall()` を使用して呼び出すかを示しています。 + +## 関連情報 + +- [emscripten.org](http://emscripten.org/) — Emscripten とそれの多種多様なオプションについての詳細を確認してください。 +- [Calling compiled C functions from JavaScript using ccall/cwrap](https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#calling-compiled-c-functions-from-javascript-using-ccall-cwrap) +- [Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process?](https://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html#why-do-functions-in-my-c-c-source-code-vanish-when-i-compile-to-javascript-and-or-i-get-no-functions-to-process) diff --git a/files/ja/webassembly/caching_modules/index.html b/files/ja/webassembly/caching_modules/index.html deleted file mode 100644 index 5264321d831696..00000000000000 --- a/files/ja/webassembly/caching_modules/index.html +++ /dev/null @@ -1,158 +0,0 @@ ---- -title: コンパイルされた WebAssembly モジュールをキャッシュする -slug: WebAssembly/Caching_modules -tags: - - Caching - - IndexedDB - - JavaScript - - Module - - WebAssembly - - compile - - wasm -translation_of: WebAssembly/Caching_modules ---- -
{{WebAssemblySidebar}}
- -
-

警告: 実験的な {{jsxref("WebAssembly.Module")}} IndexedDB のシリアル化サポートがブラウザから削除されています。{{bug("1469395")}} とこの仕様の問題を参照してください。

-
- -

キャッシングはアプリケーションのパフォーマンスを向上させるのに役立ちます — コンパイルされた WebAssembly モジュールをクライアントに格納することによって、毎回ダウンロードしてコンパイルする必要がなくなります。この記事では、キャッシングまわりのベストプラクティスについて解説します。

- -

IndexedDB を用いたキャッシング

- -

IndexedDB はクライアント側で構造化されたデータを格納、検索できるトランザクショナルデータベースシステムです。 これはテキスト、blob、他のクローン可能なオブジェクトをアプリケーションのステートの保存、アセットの永続化をするのに理想的な方法です。

- -

これには wasm モジュール ({{jsxref("WebAssembly.Module")}} JavaScript オブジェクト) も含まれます。

- -

キャッシュライブラリをセットアップする

- -

IndexedDB はやや昔ながらの API です。まず、私たちは今日のよりモダンな API にあわせて、キャッシュするコードを素早く書け、よりよく機能させるためのライブラリ関数を提供します。

- -

wasm-utils.js ライブラリスクリプト内で instantiateCachedURL() を見つけることができます— この関数は urldbVersion から wasm モジュールをフェッチし、importObject を指定してインスタンス化を行います。そして、成功時に wasm インスタンスを渡すプロミスを返します。さらに、コンパイルされた wasm モジュールをキャッシュするデータベースの作成、新しいモジュールのデータベースへの格納、事前にキャッシュされたモジュールのデータベースからの取得 (再度ダウンロードする必要がなくなります) を行います。

- -
-

: サイト全体の wasm のキャッシュ (指定されたURLだけではありません) は関数に渡す dbVersion によってバージョニングされます。wasm モジュールコードが更新された場合や、URLが変更された場合は dbVersion を更新する必要があります。以降 instantiateCachedURL() を呼び出すと、キャッシュ全体がクリアされ、期限切れのモジュールの使用を避けることができます。

-
- -

この関数はいくつかの必要な定数を定義することから始まります:

- -
function instantiateCachedURL(dbVersion, url, importObject) {
-  const dbName = 'wasm-cache';
-  const storeName = 'wasm-cache';
- -

データベースをセットアップする

- -

instantiateCachedURL() に含まれる最初のヘルパー関数 — openDatabase() — は wasm モジュールを格納するためのオブジェクトストアを作成し、 dbVersion が更新された場合はデータベースをクリアする処理をハンドリングも行います。これは解決時に新しいデータベースを渡すプロミスを返します。

- -
  function openDatabase() {
-    return new Promise((resolve, reject) => {
-      var request = indexedDB.open(dbName, dbVersion);
-      request.onerror = reject.bind(null, 'Error opening wasm cache database');
-      request.onsuccess = () => { resolve(request.result) };
-      request.onupgradeneeded = event => {
-        var db = request.result;
-        if (db.objectStoreNames.contains(storeName)) {
-            console.log(`Clearing out version ${event.oldVersion} wasm cache`);
-            db.deleteObjectStore(storeName);
-        }
-        console.log(`Creating version ${event.newVersion} wasm cache`);
-        db.createObjectStore(storeName)
-      };
-    });
-  }
- -

データベースからモジュールを検索する

- -

次の関数 — lookupInDatabase() — は上で作成したオブジェクトストアから指定した url で検索するプロミスベースの操作を提供します。解決時に格納されたコンパイル済モジュール、棄却時にエラーを渡すプロミスを返します。

- -
  function lookupInDatabase(db) {
-    return new Promise((resolve, reject) => {
-      var store = db.transaction([storeName]).objectStore(storeName);
-      var request = store.get(url);
-      request.onerror = reject.bind(null, `Error getting wasm module ${url}`);
-      request.onsuccess = event => {
-        if (request.result)
-          resolve(request.result);
-        else
-          reject(`Module ${url} was not found in wasm cache`);
-      }
-    });
-  }
- -

モジュールの保存とインスタンス化

- -

次に storeInDatabase() 関数を定義します。この関数は非同期に指定された wasm モジュールを指定したデータベースに保存します。

- -
  function storeInDatabase(db, module) {
-    var store = db.transaction([storeName], 'readwrite').objectStore(storeName);
-    var request = store.put(module, url);
-    request.onerror = err => { console.log(`Failed to store in wasm cache: ${err}`) };
-    request.onsuccess = err => { console.log(`Successfully stored ${url} in wasm cache`) };
-  }
- -

ヘルパー関数を使用する

- -

プロミスベースのヘルパー関数が全て定義されました。これらを使用して IndexDB のキャッシュルックアップするコアロジックを表現できるようになりました。データベースをオープンし、url をキーとして db に格納されているコンパイル済モジュールの有無を確認してみましょう:

- -
  return openDatabase().then(db => {
-    return lookupInDatabase(db).then(module => {
- -

成功したら、インポートオブジェクトを指定してモジュールをインスタンス化します:

- -
      console.log(`Found ${url} in wasm cache`);
-      return WebAssembly.instantiate(module, importObject);
-    },
- -

失敗した場合、スクラッチでコンパイルします。次回以降に使用するためにコンパイルしたモジュールを url をキーとしてデータベースに格納します:

- -
    errMsg => {
-      console.log(errMsg);
-      return WebAssembly.instantiateStreaming(fetch(url)).then(results => {
-        storeInDatabase(db, results.module);
-        return results.instance;
-      });
-    })
-  },
- -
-

: {{jsxref("WebAssembly.instantiate()")}} は {{jsxref("WebAssembly.Module()", "Module")}} と {{jsxref("WebAssembly.Instance()", "Instance")}} の両方を返します。Module はコンパイルされたコードを表し、IDB に格納したり、postMessage() を通じて ワーカーとの間で共有することができます。Instance はステートフルで、呼び出し可能な JavaScript の関数を含んでいるため、格納/共有することは出来ません。

-
- -

データベースをオープンすることに失敗した場合(例えば、パーミッションやクォータ等の原因による)、モジュールをフェッチしてコンパイルするだけにし、結果を格納しないでください (格納するデータベースがないため) 。

- -
  errMsg => {
-    console.log(errMsg);
-    return WebAssembly.instantiateStreaming(fetch(url)).then(results => {
-      return results.instance
-    });
-  });
-}
- -

wasm モジュールをキャッシュする

- -

上で定義されたライブラリ関数を使用して、wasm モジュールインスタンスの取得やエクスポートされた機能を使用することが (その間にバックグラウンドでキャッシュのハンドリングをしています) 、次のパラメータで呼び出すだけのシンプルなものになります:

- -
    -
  • キャッシュバージョン — 詳細は上で説明されています — wasm モジュールが更新されたときや別 URL に移動したときに更新する必要があります。
  • -
  • インスタンス化したい wasm モジュールの URL。
  • -
  • インポートオブジェクト (必要ならば)
  • -
- -
const wasmCacheVersion = 1;
-
-instantiateCachedURL(wasmCacheVersion, 'test.wasm').then(instance =>
-  console.log("Instance says the answer is: " + instance.exports.answer())
-).catch(err =>
-  console.error("Failure to instantiate: " + err)
-);
- -

ソースコードと例は GitHub の indexeddb-cache.html (動作例) を参照してください。

- -

ブラウザのサポート

- -

現時点では、WebAssembly モジュールの構造化された複製をサポートしているため、この手法は Firefox と Edge で動作します。

- -

Chrome は WebAssembly 構造化クローンサポートフラグの背後にサポートが実装されていますが、いくつかの懸念があるため、デフォルトではまだ有効にしていません (たとえば、この説明を参照)。

- -

Safari ではまだ実装されていません。

diff --git a/files/ja/webassembly/caching_modules/index.md b/files/ja/webassembly/caching_modules/index.md new file mode 100644 index 00000000000000..08d742b3725676 --- /dev/null +++ b/files/ja/webassembly/caching_modules/index.md @@ -0,0 +1,168 @@ +--- +title: コンパイルされた WebAssembly モジュールをキャッシュする +slug: WebAssembly/Caching_modules +tags: + - Caching + - IndexedDB + - JavaScript + - Module + - WebAssembly + - compile + - wasm +translation_of: WebAssembly/Caching_modules +--- +{{WebAssemblySidebar}} + +> **Warning:** **警告**: 実験的な {{jsxref("WebAssembly.Module")}} IndexedDB のシリアル化サポートがブラウザから削除されています。{{bug("1469395")}} と[この仕様の問題](https://github.com/WebAssembly/spec/issues/821)を参照してください。 + +キャッシングはアプリケーションのパフォーマンスを向上させるのに役立ちます — コンパイルされた WebAssembly モジュールをクライアントに格納することによって、毎回ダウンロードしてコンパイルする必要がなくなります。この記事では、キャッシングまわりのベストプラクティスについて解説します。 + +## IndexedDB を用いたキャッシング + +[IndexedDB](/ja/docs/Web/API/IndexedDB_API) はクライアント側で構造化されたデータを格納、検索できるトランザクショナルデータベースシステムです。 これはテキスト、blob、他のクローン可能なオブジェクトをアプリケーションのステートの保存、アセットの永続化をするのに理想的な方法です。 + +これには wasm モジュール ({{jsxref("WebAssembly.Module")}} JavaScript オブジェクト) も含まれます。 + +## キャッシュライブラリをセットアップする + +IndexedDB はやや昔ながらの API です。まず、私たちは今日のよりモダンな API にあわせて、キャッシュするコードを素早く書け、よりよく機能させるためのライブラリ関数を提供します。 + +wasm-utils.js ライブラリスクリプト内で `instantiateCachedURL()` を見つけることができます— この関数は `url` と `dbVersion` から wasm モジュールをフェッチし、`importObject` を指定してインスタンス化を行います。そして、成功時に wasm インスタンスを渡すプロミスを返します。さらに、コンパイルされた wasm モジュールをキャッシュするデータベースの作成、新しいモジュールのデータベースへの格納、事前にキャッシュされたモジュールのデータベースからの取得 (再度ダウンロードする必要がなくなります) を行います。 + +> **Note:** **注**: サイト全体の wasm のキャッシュ (指定された URL だけではありません) は関数に渡す `dbVersion` によってバージョニングされます。wasm モジュールコードが更新された場合や、URL が変更された場合は `dbVersion` を更新する必要があります。以降 `instantiateCachedURL()` を呼び出すと、キャッシュ全体がクリアされ、期限切れのモジュールの使用を避けることができます。 + +この関数はいくつかの必要な定数を定義することから始まります: + +```js +function instantiateCachedURL(dbVersion, url, importObject) { + const dbName = 'wasm-cache'; + const storeName = 'wasm-cache'; +``` + +### データベースをセットアップする + +`instantiateCachedURL()` に含まれる最初のヘルパー関数 — `openDatabase()` — は wasm モジュールを格納するためのオブジェクトストアを作成し、 `dbVersion` が更新された場合はデータベースをクリアする処理をハンドリングも行います。これは解決時に新しいデータベースを渡すプロミスを返します。 + +```js + function openDatabase() { + return new Promise((resolve, reject) => { + var request = indexedDB.open(dbName, dbVersion); + request.onerror = reject.bind(null, 'Error opening wasm cache database'); + request.onsuccess = () => { resolve(request.result) }; + request.onupgradeneeded = event => { + var db = request.result; + if (db.objectStoreNames.contains(storeName)) { + console.log(`Clearing out version ${event.oldVersion} wasm cache`); + db.deleteObjectStore(storeName); + } + console.log(`Creating version ${event.newVersion} wasm cache`); + db.createObjectStore(storeName) + }; + }); + } +``` + +### データベースからモジュールを検索する + +次の関数 — `lookupInDatabase()` — は上で作成したオブジェクトストアから指定した `url` で検索するプロミスベースの操作を提供します。解決時に格納されたコンパイル済モジュール、棄却時にエラーを渡すプロミスを返します。 + +```js + function lookupInDatabase(db) { + return new Promise((resolve, reject) => { + var store = db.transaction([storeName]).objectStore(storeName); + var request = store.get(url); + request.onerror = reject.bind(null, `Error getting wasm module ${url}`); + request.onsuccess = event => { + if (request.result) + resolve(request.result); + else + reject(`Module ${url} was not found in wasm cache`); + } + }); + } +``` + +### モジュールの保存とインスタンス化 + +次に `storeInDatabase()` 関数を定義します。この関数は非同期に指定された wasm モジュールを指定したデータベースに保存します。 + +```js + function storeInDatabase(db, module) { + var store = db.transaction([storeName], 'readwrite').objectStore(storeName); + var request = store.put(module, url); + request.onerror = err => { console.log(`Failed to store in wasm cache: ${err}`) }; + request.onsuccess = err => { console.log(`Successfully stored ${url} in wasm cache`) }; + } +``` + +### ヘルパー関数を使用する + +プロミスベースのヘルパー関数が全て定義されました。これらを使用して IndexDB のキャッシュルックアップするコアロジックを表現できるようになりました。データベースをオープンし、`url` をキーとして `db` に格納されているコンパイル済モジュールの有無を確認してみましょう: + +```js + return openDatabase().then(db => { + return lookupInDatabase(db).then(module => { +``` + +成功したら、インポートオブジェクトを指定してモジュールをインスタンス化します: + +```js + console.log(`Found ${url} in wasm cache`); + return WebAssembly.instantiate(module, importObject); + }, +``` + +失敗した場合、スクラッチでコンパイルします。次回以降に使用するためにコンパイルしたモジュールを url をキーとしてデータベースに格納します: + +```js + errMsg => { + console.log(errMsg); + return WebAssembly.instantiateStreaming(fetch(url)).then(results => { + storeInDatabase(db, results.module); + return results.instance; + }); + }) + }, +``` + +> **Note:** **注**: {{jsxref("WebAssembly.instantiate()")}} は {{jsxref("WebAssembly.Module()", "Module")}} と {{jsxref("WebAssembly.Instance()", "Instance")}} の両方を返します。Module はコンパイルされたコードを表し、IDB に格納したり、[`postMessage()`](/ja/docs/Web/API/MessagePort/postMessage) を通じて ワーカーとの間で共有することができます。Instance はステートフルで、呼び出し可能な JavaScript の関数を含んでいるため、格納/共有することは出来ません。 + +データベースをオープンすることに失敗した場合(例えば、パーミッションやクォータ等の原因による)、モジュールをフェッチしてコンパイルするだけにし、結果を格納しないでください (格納するデータベースがないため) 。 + +```js + errMsg => { + console.log(errMsg); + return WebAssembly.instantiateStreaming(fetch(url)).then(results => { + return results.instance + }); + }); +} +``` + +## wasm モジュールをキャッシュする + +上で定義されたライブラリ関数を使用して、wasm モジュールインスタンスの取得やエクスポートされた機能を使用することが (その間にバックグラウンドでキャッシュのハンドリングをしています) 、次のパラメータで呼び出すだけのシンプルなものになります: + +- キャッシュバージョン — 詳細は上で説明されています — wasm モジュールが更新されたときや別 URL に移動したときに更新する必要があります。 +- インスタンス化したい wasm モジュールの URL。 +- インポートオブジェクト (必要ならば) + +```js +const wasmCacheVersion = 1; + +instantiateCachedURL(wasmCacheVersion, 'test.wasm').then(instance => + console.log("Instance says the answer is: " + instance.exports.answer()) +).catch(err => + console.error("Failure to instantiate: " + err) +); +``` + +ソースコードと例は GitHub の [indexeddb-cache.html](https://github.com/mdn/webassembly-examples/blob/master/other-examples/indexeddb-cache.html) ([動作例](https://mdn.github.io/webassembly-examples/other-examples/indexeddb-cache.html)) を参照してください。 + +## ブラウザのサポート + +現時点では、WebAssembly モジュールの構造化された複製をサポートしているため、この手法は Firefox と Edge で動作します。 + +Chrome は WebAssembly 構造化クローンサポートフラグの背後にサポートが実装されていますが、いくつかの懸念があるため、デフォルトではまだ有効にしていません (たとえば、[この説明を参照](https://github.com/WebAssembly/design/issues/972))。 + +Safari ではまだ実装されていません。 diff --git a/files/ja/webassembly/concepts/index.html b/files/ja/webassembly/concepts/index.html deleted file mode 100644 index 9e94a90ddbaf54..00000000000000 --- a/files/ja/webassembly/concepts/index.html +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: WebAssembly の概要 -slug: WebAssembly/Concepts -tags: - - C - - C++ - - Emscripten - - JavaScript - - Web プラットフォーム - - WebAssembly - - rust -translation_of: WebAssembly/Concepts ---- -
{{WebAssemblySidebar}}
- -

この記事では、 WebAssembly がどのように機能しているか、その目標、解決している問題、ウェブブラウザーのレンダリングエンジン内での動作などの概念について説明します。

- -

WebAssembly とは何か

- -

WebAssembly は最近のウェブブラウザーで動作し、新たな機能と大幅なパフォーマンス向上を提供する新しい種類のコードです。基本的に直接記述ではなく、C、C++、Rust 等の低水準の言語にとって効果的なコンパイル対象となるように設計されています。

- -

この機能はウェブプラットフォームにとって大きな意味を持ちます。 — ウェブ上で動作するクライアントアプリで従来は実現できなかった、ネイティブ水準の速度で複数の言語で記述されたコードをウェブ上で動作させる方法を提供します。

- -

それ以上に、その利点を享受するために利用者は WebAssembly のコードをどのように作成するのか知る必要さえ有りません。 WebAssembly モジュールはウェブ (あるいは Node.js) アプリにインポートする事ができ、 WebAssembly の機能は JavaScript を経由して他の領域から利用できる状態になります。 JavaScript 製フレームワークでは大幅なパフォーマンス改善と開発中の新機能をウェブ開発者が容易に利用できるようにするために WebAssembly を用いることができます。

- -

WebAssembly の目標

- -

WebAssembly は W3C WebAssembly Community Group 内で策定されるオープン標準として以下を目標に定めて作成されています:

- -
    -
  • 高速で、高効率であり、ポータブルである事 — WebAssembly のコードは 共通ハードウェア対応環境 を利用して異なるプラットフォーム間でネイティブ水準の速度で実行可能です。
  • -
  • 可読性を持ちデバッグ可能である事 — WebAssembly は低水準のアセンブリ言語ですが、人間が読めるテキストフォーマットを持ちます(その仕様策定は終わっていないものの)。このフォーマットは人の手で読み書きできて、デバッグもできます。
  • -
  • 安全である事 — WebAssembly は安全でサンドボックス化された実行環境上で動作するように設計されています。他のウェブ言語と同様に、ブラウザーに対して same-origin および権限ポリシーの確認を強制します。
  • -
  • ウェブを破壊しない事 — WebAssembly は他のウェブ技術と協調し、後方互換性を維持するように設計されます。
  • -
- -
-

メモ: WebAssembly はまたウェブの領域外の JavaScript 環境での利用も行います (Non-web embeddings を参照)。

-
- -

WebAssembly はどのようにウェブプラットフォームに適合するのか

- -

ウェブプラットフォームは 2 つの領域からなると考える事ができます:

- -
    -
  • ウェブアプリのコードを実行する仮想マシン (VM) 、例としてアプリを動作させる JavaScript コード。
  • -
  • ウェブブラウザー / デバイスの機能をコントロールして物事を実現するためにウェブアプリが呼ぶことのできる Web API のセット (DOMCSSOMWebGLIndexedDBWeb Audio API 等)。
  • -
- -

歴史的に、仮想マシンは JavaScript を読み込む事しかできませんでした。 JavaScript が今日のウェブで人々が遭遇する多くの問題を解決する上で十分にパワフルであるため私達にとって仮想マシンはとても有効でした。しかしながら私達は JavaScript をもっと厳しい状況、3D ゲーム、VR に AR、コンピュータービジョン、画像/動画編集等ネイティブの性能が要求されるような多くの領域 (これら以外の利用アイディアに関しては WebAssembly use cases を参照) において用いる際にパフォーマンス上の問題に遭遇するようになっています。

- -

加えて巨大な JavaScript アプリケーションのダウンロード、構造の解析とコンパイルのコストは異常に高いものになりえます。モバイルや他のリソースが限られたプラットフォームではこのようなパフォーマンスのボトルネックの影響をずっと強く受ける事になります。

- -

WebAssembly は JavaScript と異なる言語ですが、その置き換えを意図していません。その代わり、JavaScript の足りない所を補填して併用し、ウェブ開発者に双方の以下のような利益を提供する事を狙いとしています:

- -
    -
  • JavaScript は高水準の言語であり、ウェブアプリケーションを作る上で十分な柔軟性と表現力を持っています。そして多くの利点 — 動的型付け言語である、コンパイルが必須でない、パワフルなフレームワーク、ライブラリやツールを提供する豊富な土壌等を持っています。
  • -
  • WebAssembly はネイティブに近いパフォーマンスで動作して、C++ や Rust のような低水準のメモリー管理を行う言語がウェブ上で動作するようコンパイルされる対象となる、コンパクトなバイナリー形式を持つ低水準なアセンブリに似た言語です (WebAssembly は将来的にガベージコレクションによるメモリー管理を行う言語をサポートする 高レベルの目標 を持っている事に注意してください)。
  • -
- -

ブラウザーにおいての WebAssembly の登場によって、私たちが先述したような仮想マシンはこれから 2 つの種類の言語をロードして実行することになります — JavaScript と WebAssembly です。

- -

必要に応じてこの異なったコードは互いを呼び出し合う事ができます — WebAssembly JavaScript API はエクスポートした WebAssembly のコードを普遍的に呼び出せる JavaScript 関数でラップし、WebAssembly のコードは通常の JavaScript 関数をインポートして同期的に呼び出せます。実際、WebAssembly のコードの基本単位はモジュールと呼ばれ、 WebAssembly のモジュールは ES2015 のモジュールと多くの対になる概念を持っています。

- -

WebAssembly のキーコンセプト

- -

ブラウザー上で WebAssembly がどのように動作するかを理解するため必要となるキーコンセプトがいくつか存在します。これらのコンセプトはそれぞれが WebAssembly JavaScript API に一対一で対応しています。

- -
    -
  • Module (モジュール): ブラウザーによって実行可能な機械語にコンパイルされた WebAssembly のバイナリーに対応します。モジュールはステートレスであるため、Blob のように、明示的に IndexedDB にキャッシュ できたり window やウェブワーカーと ( postMessage() を経由して ) 共有する事ができます。モジュールは ES2015 のモジュールのように import と export の宣言を行います。
  • -
  • Memory (メモリー): WebAssembly の低水準なメモリーアクセス命令によって読み込みおよび書き込みが行われるバイト列を一次元の配列として保持している、リサイズ可能な ArrayBuffer です。
  • -
  • Table (テーブル): メモリー内に (安全性およびポータブル性を維持するため) バイト列として保持することができなかった (関数等に対する) 参照を保持しているリサイズ可能な型付き配列です。
  • -
  • Instance (インスタンス): メモリー、テーブル、インポートされた値を含む実行時に利用されるすべての状態と対となるモジュールです。インスタンスは特定の import によって特定のグローバル環境にロードされた ES2015 におけるモジュールのような物です。
  • -
- -

JavaScript API はモジュール、メモリー、テーブルおよびインスタンスを作る機能を開発者に提供します。 WebAssembly のインスタンスが与えられれば、 JavaScript はその中で export されたオブジェクトを、一般的な JavaScript で渡せる状態にされた関数同様に、同期的に呼び出すことができます。また任意の JavaScript の関数はその関数を WebAssembly のインスタンスに import する事で WebAssembly のコードから同期的に呼び出されるようにする事もできます。

- -

JavaScript は WebAssembly のコードがどのようにダウンロードされ、コンパイルされて実行されるかを完全に制御できるため、JavaScript 開発者は WebAssembly を単に効果的に高いパフォーマンスを発揮する JavaScript の機能のようにとらえることもできます。

- -

将来的には、 WebAssembly モジュールは (<script type='module'> を利用して) ES2015 モジュールのようにロード可能 となり、これは JavaScript が WebAssembly モジュールを ES2015 モジュールと同じくらい簡単に取得、コンパイル、インポートできるようになる事を意味します。

- -

WebAssembly をどのようにアプリで用いるか

- -

ここまで私たちは WebAssembly がウェブプラットフォームに付加する基本的な原則について話しました。つまりコードのバイナリー形式とバイナリーコードを読み込み実行する API について。ここからは実際にこれらの原則をどのように活かすのかについて話します。

- -

WebAssembly のエコシステムはまだ黎明期の状態にあります。もっと多くのツール群によってこの状況が進展するのは間違いありません。現時点では主に4つの入口があります。

- -
    -
  • Emscripten を用いて C/C++ 製アプリケーションをポーティングする。
  • -
  • アセンブリ水準で WebAssembly を記述もしくは直接生成する。
  • -
  • Rust アプリケーションを書き、 WebAssembly を出力ターゲットとする。
  • -
  • TypeScript によく似た AssemblyScript を用いて、 WebAssembly バイナリーに出力する
  • -
- -

これらの選択肢について考えてみましょう。

- -

C/C++ からのポーティング

- -

WASM コードを作成するための多くのオプションのうちの 2 つは、オンラインの Wasm アセンブラまたは Emscripten です。 WASM のオンラインアセンブラには、次のようなものがあります。

- - - -

これらは、どこから始めるべきかを把握しようとしている人にとっては素晴らしいリソースですが、 Emscripten のツールと最適化には欠けています。

- -

Emscripten ツールは C/C++ ソースコードを取得し、それを .wasm モジュール、加えてモジュールを読みだして実行するために必要な JavaScript に "glue" コードとコードの結果を表示するための HTML 文章にコンパイルおよび出力します。

- -

- -

簡潔に言えば、このプロセスは以下のような物になります。

- -
    -
  1. Emscripten は最初に C/C++ を Clang + LLVM — 完成度の高いオープンソースの C/C++ コンパイラ・ツールチェインであり、OSX の XCode の一部として提供される等の利用例が有る、に注入します。
  2. -
  3. Emscripten が Clang + LLVM によるコンパイル結果を .wasm バイナリーに変換します。
  4. -
  5. それ自体だけでは WebAssembly は現時点で DOM に直接アクセスできません; JavaScript を呼び出して、整数型もしくは浮動小数点型の基本データを渡せるだけです。そのため、ウェブ API にアクセスするためには、WebAssembly は JavaScript を呼び出す必要が有り、この時点でウェブ API の呼び出しが行われます。そのため Emscripten は結果を得るための HTML と JavaScript のグルーコードを生成します。
  6. -
- -
-

メモ: 将来的に WebAssembly に直接ウェブ API を呼ばせる事を許容する 計画があります。

-
- -

JavaScript グルーコードは多くの人が想像するほど簡単な構造をしていません。はじめに、 Emscripten は SDLOpenGLOpenAL および POSIX の一部といった主な C/C++ ライブラリを組み込みます。これらのライブラリ群はウェブ API の観点から組み込まれ、各々が WebAssembly を既存のウェブ API に接続するためにいくつかの JavaScript グルーコードを必要とします。

- -

そのためグルーコードの一部は C/C++ コードによって利用されるそれぞれのライブラリの機能を組み込みます。グルーコードはまた .wasm ファイルを取得、ロード、実行するため先述した WebAssembly JavaScript API を呼び出すロジックも含んでいます。

- -

生成された HTML 文章は JavaScript グルーコードのファイルを読み込んで {{htmlelement("textarea")}} に標準出力を書き出します。もしアプリケーションが OpenGL を利用している場合、その HTML はまた出力先となる {{htmlelement("canvas")}} 要素を含みます。Emscripten の出力結果を修正して必要とするウェブアプリに変換するのは非常に簡単です。

- -

Emscripten に関する完全なドキュメントは emscripten.org で参照でき、このツールチェインの組み込みと自身の C/C++ アプリを wasm へとコンパイルするガイドとしては C/C++ を WebAssembly にコンパイルする が参考になります。

- -

直接 WebAssembly を記述する

- -

独自のコンパイラ、ツール、あるいは WebAssembly を実行時に生成する JavaScript のライブラリを作りたいとお考えですか ?

- -

実際のアセンブリ言語同様、 WebAssembly バイナリー形式はテキスト表現を持っています — これらは一対一で対応しています。なんらかの WebAssemby テキスト表現バイナリー変換ツール を用いることでテキスト表現を直接記述してバイナリー形式に変換することができます。

- -

この手順に関しては、 WebAssembly テキスト表現を wasm 形式に変換する の項目を参照ください。

- -

WebAssembly をターゲットとした Rust の記述

- -

Rust WebAssembly ワーキンググループの不断の仕事のおかげで、Rust コードを書いて WebAssembly にコンパイルすることも可能です。必要なツールチェーンをインストールし、サンプル Rust プログラムを WebAssembly npm パッケージにコンパイルし、ウェブアプリケーションのサンプルを使用して、 Rust から WebAssembly へのコンパイルの記事を読むことができます。

- -

AssemblyScript の使用

- -

C や Rust を学ぶ必要なく WebAssembly を試してみたいウェブ開発者には、 AssemblyScript が最良の選択肢です。これは小さなバンドルを生成し、 C や Rust と比較するとやや遅い程度です。ドキュメントは https://assemblyscript.org/ でチェックすることができます。

- -

まとめ

- -

本項目では WebAssembly が何であるか、どういった利便性が有るか、どのようにしてウェブに適用するかとどのように活用するかについて説明しました。

- -

関連情報

- - diff --git a/files/ja/webassembly/concepts/index.md b/files/ja/webassembly/concepts/index.md new file mode 100644 index 00000000000000..5b954f25586d2e --- /dev/null +++ b/files/ja/webassembly/concepts/index.md @@ -0,0 +1,140 @@ +--- +title: WebAssembly の概要 +slug: WebAssembly/Concepts +tags: + - C + - C++ + - Emscripten + - JavaScript + - Web プラットフォーム + - WebAssembly + - rust +translation_of: WebAssembly/Concepts +--- +{{WebAssemblySidebar}} + +この記事では、 WebAssembly がどのように機能しているか、その目標、解決している問題、ウェブブラウザーのレンダリングエンジン内での動作などの概念について説明します。 + +## WebAssembly とは何か + +WebAssembly は最近のウェブブラウザーで動作し、新たな機能と大幅なパフォーマンス向上を提供する新しい種類のコードです。基本的に直接記述ではなく、C、C++、Rust 等の低水準の言語にとって効果的なコンパイル対象となるように設計されています。 + +この機能はウェブプラットフォームにとって大きな意味を持ちます。 — ウェブ上で動作するクライアントアプリで従来は実現できなかった、ネイティブ水準の速度で複数の言語で記述されたコードをウェブ上で動作させる方法を提供します。 + +それ以上に、その利点を享受するために利用者は WebAssembly のコードをどのように作成するのか知る必要さえ有りません。 WebAssembly モジュールはウェブ (あるいは Node.js) アプリにインポートする事ができ、 WebAssembly の機能は JavaScript を経由して他の領域から利用できる状態になります。 JavaScript 製フレームワークでは大幅なパフォーマンス改善と開発中の新機能をウェブ開発者が容易に利用できるようにするために WebAssembly を用いることができます。 + +## WebAssembly の目標 + +WebAssembly は [W3C WebAssembly Community Group](https://www.w3.org/community/webassembly/) 内で策定されるオープン標準として以下を目標に定めて作成されています: + +- 高速で、高効率であり、ポータブルである事 — WebAssembly のコードは [共通ハードウェア対応環境](http://webassembly.org/docs/portability/#assumptions-for-efficient-execution) を利用して異なるプラットフォーム間でネイティブ水準の速度で実行可能です。 +- 可読性を持ちデバッグ可能である事 — WebAssembly は低水準のアセンブリ言語ですが、人間が読めるテキストフォーマットを持ちます(その仕様策定は終わっていないものの)。このフォーマットは人の手で読み書きできて、デバッグもできます。 +- 安全である事 — WebAssembly は安全でサンドボックス化された実行環境上で動作するように設計されています。他のウェブ言語と同様に、ブラウザーに対して same-origin および権限ポリシーの確認を強制します。 +- ウェブを破壊しない事 — WebAssembly は他のウェブ技術と協調し、後方互換性を維持するように設計されます。 + +> **Note:** **メモ**: WebAssembly はまたウェブの領域外の JavaScript 環境での利用も行います ([Non-web embeddings](http://webassembly.org/docs/non-web/) を参照)。 + +## WebAssembly はどのようにウェブプラットフォームに適合するのか + +ウェブプラットフォームは 2 つの領域からなると考える事ができます: + +- ウェブアプリのコードを実行する仮想マシン (VM) 、例としてアプリを動作させる JavaScript コード。 +- ウェブブラウザー / デバイスの機能をコントロールして物事を実現するためにウェブアプリが呼ぶことのできる [Web API](/ja/docs/Web/API) のセット ([DOM](/ja/docs/Web/API/Document_Object_Model)、 [CSSOM](/ja/docs/Web/API/CSS_Object_Model)、 [WebGL](/ja/docs/Web/API/WebGL_API)、 [IndexedDB](/ja/docs/Web/API/IndexedDB_API)、 [Web Audio API](/ja/docs/Web/API/Web_Audio_API) 等)。 + +歴史的に、仮想マシンは JavaScript を読み込む事しかできませんでした。 JavaScript が今日のウェブで人々が遭遇する多くの問題を解決する上で十分にパワフルであるため私達にとって仮想マシンはとても有効でした。しかしながら私達は JavaScript をもっと厳しい状況、3D ゲーム、VR に AR、コンピュータービジョン、画像/動画編集等ネイティブの性能が要求されるような多くの領域 (これら以外の利用アイディアに関しては [WebAssembly use cases](http://webassembly.org/docs/use-cases/) を参照) において用いる際にパフォーマンス上の問題に遭遇するようになっています。 + +加えて巨大な JavaScript アプリケーションのダウンロード、構造の解析とコンパイルのコストは異常に高いものになりえます。モバイルや他のリソースが限られたプラットフォームではこのようなパフォーマンスのボトルネックの影響をずっと強く受ける事になります。 + +WebAssembly は JavaScript と異なる言語ですが、その置き換えを意図していません。その代わり、JavaScript の足りない所を補填して併用し、ウェブ開発者に双方の以下のような利益を提供する事を狙いとしています: + +- JavaScript は高水準の言語であり、ウェブアプリケーションを作る上で十分な柔軟性と表現力を持っています。そして多くの利点 — 動的型付け言語である、コンパイルが必須でない、パワフルなフレームワーク、ライブラリやツールを提供する豊富な土壌等を持っています。 +- WebAssembly はネイティブに近いパフォーマンスで動作して、C++ や Rust のような低水準のメモリー管理を行う言語がウェブ上で動作するようコンパイルされる対象となる、コンパクトなバイナリー形式を持つ低水準なアセンブリに似た言語です (WebAssembly は将来的にガベージコレクションによるメモリー管理を行う言語をサポートする [高レベルの目標](http://webassembly.org/docs/high-level-goals/) を持っている事に注意してください)。 + +ブラウザーにおいての WebAssembly の登場によって、私たちが先述したような仮想マシンはこれから 2 つの種類の言語をロードして実行することになります — JavaScript と WebAssembly です。 + +必要に応じてこの異なったコードは互いを呼び出し合う事ができます — [WebAssembly JavaScript API](/ja/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) はエクスポートした WebAssembly のコードを普遍的に呼び出せる JavaScript 関数でラップし、WebAssembly のコードは通常の JavaScript 関数をインポートして同期的に呼び出せます。実際、WebAssembly のコードの基本単位はモジュールと呼ばれ、 WebAssembly のモジュールは ES2015 のモジュールと多くの対になる概念を持っています。 + +### WebAssembly のキーコンセプト + +ブラウザー上で WebAssembly がどのように動作するかを理解するため必要となるキーコンセプトがいくつか存在します。これらのコンセプトはそれぞれが [WebAssembly JavaScript API](/ja/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) に一対一で対応しています。 + +- **Module (モジュール)**: ブラウザーによって実行可能な機械語にコンパイルされた WebAssembly のバイナリーに対応します。モジュールはステートレスであるため、[Blob](/ja/docs/Web/API/Blob) のように、明示的に [IndexedDB にキャッシュ](/ja/docs/WebAssembly/Caching_modules) できたり window やウェブワーカーと ( [`postMessage()`](/ja/docs/Web/API/MessagePort/postMessage) を経由して ) 共有する事ができます。モジュールは ES2015 のモジュールのように import と export の宣言を行います。 +- **Memory (メモリー)**: WebAssembly の低水準なメモリーアクセス命令によって読み込みおよび書き込みが行われるバイト列を一次元の配列として保持している、リサイズ可能な ArrayBuffer です。 +- **Table (テーブル)**: メモリー内に (安全性およびポータブル性を維持するため) バイト列として保持することができなかった (関数等に対する) 参照を保持しているリサイズ可能な型付き配列です。 +- **Instance (インスタンス)**: メモリー、テーブル、インポートされた値を含む実行時に利用されるすべての状態と対となるモジュールです。インスタンスは特定の import によって特定のグローバル環境にロードされた ES2015 におけるモジュールのような物です。 + +JavaScript API はモジュール、メモリー、テーブルおよびインスタンスを作る機能を開発者に提供します。 WebAssembly のインスタンスが与えられれば、 JavaScript はその中で export されたオブジェクトを、一般的な JavaScript で渡せる状態にされた関数同様に、同期的に呼び出すことができます。また任意の JavaScript の関数はその関数を WebAssembly のインスタンスに import する事で WebAssembly のコードから同期的に呼び出されるようにする事もできます。 + +JavaScript は WebAssembly のコードがどのようにダウンロードされ、コンパイルされて実行されるかを完全に制御できるため、JavaScript 開発者は WebAssembly を単に効果的に高いパフォーマンスを発揮する JavaScript の機能のようにとらえることもできます。 + +将来的には、 WebAssembly モジュールは (` + +``` + +そして、正しいバージョン番号が[出力](https://googlechrome.github.io/samples/webassembly/version.html)されます: + +![ 正しいバージョン番号を示すデベロッパーツールのコンソールのスクリーンショット](https://mdn.mozillademos.org/files/15913/version.png) + +> **Note:** **注:** libwebp は現在のバージョン a.b.c を 16 進数の 0xabc で返します。例えば、v0.6.1 は 0x000601 = 1537 としてエンコードされています。 + +### JavaScript から Wasm に画像を取得する + +エンコーダのバージョン番号を取得するのは素晴らしいことですが、画像をエンコードした方が印象的です。どうすればいいのでしょうか? + +最初に答えなければならない質問は、どうやって画像を wasm に入れるのかということです。libwebp の[Encoding API](https://developers.google.com/speed/webp/docs/api#simple_encoding_api)を見ると、RGB、RGBA、BGR、BGRA のバイト列を期待していることがわかります。幸いにも Canvas API には {{domxref("CanvasRenderingContext2D.getImageData")}} があり、RGBA の画像データを含む {{jsxref("Uint8ClampedArray")}}が得られます: + +```js + async function loadImage(src) { + // Load image + const imgBlob = await fetch(src).then(resp => resp.blob()); + const img = await createImageBitmap(imgBlob); + // Make canvas same size as image + const canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + // Draw image onto canvas + const ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + return ctx.getImageData(0, 0, img.width, img.height); +} +``` + +これで、JavaScript から wasm にデータをコピーすることだけが「唯一の」問題となります。そのためには、追加で 2 つの関数を公開する必要があります — 1 つは、wasm 内で画像のためにメモリを確保する関数、もう 1 つは、それを再び解放する関数です: + +```cpp +#include // required for malloc definition + +EMSCRIPTEN_KEEPALIVE +uint8_t* create_buffer(int width, int height) { + return malloc(width * height * 4 * sizeof(uint8_t)); +} + +EMSCRIPTEN_KEEPALIVE +void destroy_buffer(uint8_t* p) { + free(p); +} +``` + +`create_buffer()` 関数は RGBA 画像用 — したがって、ピクセル当たり 4 バイト — のバッファを確保します。malloc() が返すポインタは、そのバッファの最初のメモリセルのアドレスです。ポインタが JavaScript に返されると、それは単なる数値として扱われます。この関数を cwrap を使って JavaScript に公開した後、その数値を使ってバッファの開始点を見つけ、画像データをコピーすることができます。 + +```js +const api = { + version: Module.cwrap('version', 'number', []), + create_buffer: Module.cwrap('create_buffer', 'number', ['number', 'number']), + destroy_buffer: Module.cwrap('destroy_buffer', '', ['number']), +}; + +const image = await loadImage('./image.jpg'); +const p = api.create_buffer(image.width, image.height); +Module.HEAP8.set(image.data, p); +// ... call encoder ... +api.destroy_buffer(p); +``` + +### 画像をエンコードする + +wasm で画像を使えるようになりました。いよいよ WebP エンコーダを呼び出して動かす時が来ました。[WebP のドキュメント](https://developers.google.com/speed/webp/docs/api#simple_encoding_api)を見ると、`WebPEncodeRGBA`がふさわしいようです。この関数は、入力画像へのポインタと画像の寸法、そして 0 から 100 の間のクオリティーオプションを受け取ります。また、出力バッファを確保するので、WebP 画像の処理が終わったら `WebPFree()`を使って解放する必要があります。 + +エンコード処理の結果は、出力バッファとその長さになります。C 言語の関数は(メモリを動的に確保しない限り)戻り値の型として配列を使うことができないため 、この例では静的なグローバル配列を使用しています。これはクリーンな C 言語とは言えないかもしれません。実際、これは wasm ポインタが 32 ビット幅であることに依存しています。しかし、これは話を単純にするための公正な手段です。 + +```js +int result[2]; +EMSCRIPTEN_KEEPALIVE +void encode(uint8_t* img_in, int width, int height, float quality) { + uint8_t* img_out; + size_t size; + + size = WebPEncodeRGBA(img_in, width, height, width * 4, quality, &img_out); + + result[0] = (int)img_out; + result[1] = size; +} + +EMSCRIPTEN_KEEPALIVE +void free_result(uint8_t* result) { + WebPFree(result); +} + +EMSCRIPTEN_KEEPALIVE +int get_result_pointer() { + return result[0]; +} + +EMSCRIPTEN_KEEPALIVE +int get_result_size() { + return result[1]; +} +``` + +これで、エンコーディング関数を呼び出し、ポインタと画像サイズを取得し、それをあなたの JavaScript バッファに格納し、プロセス中で確保されたすべての wasm バッファを解放することができるようになりました。 + +```js +api.encode(p, image.width, image.height, 100); +const resultPointer = api.get_result_pointer(); +const resultSize = api.get_result_size(); +const resultView = new Uint8Array(Module.HEAP8.buffer, resultPointer, resultSize); +const result = new Uint8Array(resultView); +api.free_result(resultPointer); +``` + +> **Note:** `new Uint8Array(someBuffer)`は同じメモリチャンク上に新しいビューを作成し、`new Uint8Array(someTypedArray)`はデータをコピーします。 + +画像のサイズによっては、wasm が入力画像と出力画像を格納するためのメモリを十分に大きくすることができないというエラーが発生する可能性があります: + +![ + Screenshot of the DevTools console showing an error.](https://mdn.mozillademos.org/files/15922/error.png) + +幸いにも、この問題の解決策はエラーメッセージの中にあります。コンパイルコマンドに`-s ALLOW_MEMORY_GROWTH=1`を追加するだけです。 + +これで完了です。WebP エンコーダをコンパイルし、JPEG 画像を WebP にトランスコードしました。うまくいったことを証明するために、結果のバッファを blob にして``要素で使用してください: + +```js +const blob = new Blob([result], {type: 'image/webp'}); +const blobURL = URL.createObjectURL(blob); +const img = document.createElement('img'); +img.src = blobURL; +document.body.appendChild(img) +``` + +見るがいい、新しい WebP 画像の栄光を。 + +[デモ](https://googlechrome.github.io/samples/webassembly/image.html) | [原著](https://developers.google.com/web/updates/2018/03/emscripting-a-c-library) + +![ デベロッパーツールのネットワークパネルと生成された画像。](https://mdn.mozillademos.org/files/15914/result.jpg) diff --git a/files/ja/webassembly/exported_functions/index.html b/files/ja/webassembly/exported_functions/index.html deleted file mode 100644 index c1b696898dc0b4..00000000000000 --- a/files/ja/webassembly/exported_functions/index.html +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: エクスポートされた WebAssembly 関数 -slug: WebAssembly/Exported_functions -tags: - - Guide - - JavaScript - - WebAssembly - - export - - exported functions - - exported wasm functions - - wasm -translation_of: WebAssembly/Exported_functions ---- -
{{WebAssemblySidebar}}
- -

エクスポートされた WebAssembly 関数は WebAssembly 関数が JavaScript でどのように表現されるのか、この記事では、もう少し詳しく説明します。

- -

エクスポートされた...とは?

- -

エクスポートされた WebAssembly 関数は WebAssembly 関数を表現する JavaScript ラッパーです。それらを呼び出したときにバックグラウンドでいくつかの動作を行います。引数を wasm で使える型に(例えば、JavaScript の数値を Int32 に)変換し、wasm モジュール内の関数に渡し、実行し、結果を変換して JavaScript 側に戻します。

- -

エクスポートされた WebAssembly 関数は次の 2 つの方法で取得できます:

- -
    -
  • 既存のテーブルの Table.prototype.get() を呼び出す。
  • -
  • wasm モジュールインスタンスの Instance.exports を通してエクスポートされた関数にアクセスする。
  • -
- -

いずれにしても、同じ種類の内在する関数のラッパーを取得できます。JavaScript からみると、すべての wasm 関数は JavaScript 関数のようにみえます。しかし、これは wasm 関数オブジェクトインスタンスによってカプセル化されており、アクセスする方法は限られています。

- -

- -

物事を明らかにするために例を見ていきましょう(例は GitHub の table-set.html動作例、wasm の テキスト表現 を参照してください):

- -
var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });
-
-WebAssembly.instantiateStreaming(fetch('table.wasm'))
-.then(function(obj) {
-  var tbl = obj.instances.exports.tbl;
-  console.log(tbl.get(0)());  // 13
-  console.log(tbl.get(1)());  // 42
-  otherTable.set(0,tbl.get(0));
-  otherTable.set(1,tbl.get(1));
-  console.log(otherTable.get(0)());
-  console.log(otherTable.get(1)());
-});
- -

ここでは、{{jsxref("WebAssembly.Table")}} コンストラクタを使用して JavaScript からテーブル(otherTable)を作成し、{{jsxref("WebAssembly.instantiateStreaming()")}} ユーティリティ関数を使用して table.wasm をページに読み込みます。

- -

そのあと、モジュールからエクスポートされた関数を取得し、関数の参照を tbl.get() を通して取り出し、それぞれを実行した結果をコンソールに出力します。次に、 set() を使用して、tbl テーブルと同じ関数への参照を otherTable テーブルに含まれるようにします。

- -

確認するために、otherTable から参照を取得し直し、その結果もコンソールに出力します(同じ結果が得られます)。

- -

それらは本当の関数です

- -

前の例で、Table.prototype.get() のそれぞれの返り値はエクスポートされた WebAssembly 関数でした。まさに私達が話していたことです。

- -

これらは WebAssembly 関数のラッパーであるのに加えて本当の JavaScript 関数 であることに注意してください。上の例を WebAssembly をサポートするブラウザーでロードして、コンソール上で実行すると:

- -
var testFunc = otherTable.get(0);
-typeof testFunc;
- -

結果として関数が返されます。この関数は他の JavaScript の他の 関数 と同じように扱うことができます(call()bind()、その他)。testFunc.toString() は興味深い結果を返します:

- -
function 0() {
-    [native code]
-}
- -

これはラッパー型の性質のアイデアの多くを提供します。

- -

エクスポートされた WebAssembly 関数について他の注意事項は:

- -
    -
  • length プロパティは wasm 内の関数シグネチャで宣言されている引数の数です。
  • -
  • name プロパティは toString() の結果で見えている wasm モジュール内での関数のインデックスです。
  • -
  • i64 型の値を受け取る、または返すエクスポートされた wasm 関数を呼び出そうとすると、現在 JavaScript 上で i64 を表現する的確な方法がないためエラーをスローします。これは将来的に変わる可能性があります。新しい int64 型が将来の標準で検討されており、wasm によって使用される可能性があります。
  • -
diff --git a/files/ja/webassembly/exported_functions/index.md b/files/ja/webassembly/exported_functions/index.md new file mode 100644 index 00000000000000..2aad08f2d5ae3c --- /dev/null +++ b/files/ja/webassembly/exported_functions/index.md @@ -0,0 +1,79 @@ +--- +title: エクスポートされた WebAssembly 関数 +slug: WebAssembly/Exported_functions +tags: + - Guide + - JavaScript + - WebAssembly + - export + - exported functions + - exported wasm functions + - wasm +translation_of: WebAssembly/Exported_functions +--- +{{WebAssemblySidebar}} + +エクスポートされた WebAssembly 関数は WebAssembly 関数が JavaScript でどのように表現されるのか、この記事では、もう少し詳しく説明します。 + +## エクスポートされた...とは? + +エクスポートされた WebAssembly 関数は WebAssembly 関数を表現する JavaScript ラッパーです。それらを呼び出したときにバックグラウンドでいくつかの動作を行います。引数を wasm で使える型に(例えば、JavaScript の数値を Int32 に)変換し、wasm モジュール内の関数に渡し、実行し、結果を変換して JavaScript 側に戻します。 + +エクスポートされた WebAssembly 関数は次の 2 つの方法で取得できます: + +- 既存のテーブルの [`Table.prototype.get()`](/ja/docs/WebAssembly/API/Table/get) を呼び出す。 +- wasm モジュールインスタンスの [`Instance.exports`](/ja/docs/WebAssembly/API/Instance/exports) を通してエクスポートされた関数にアクセスする。 + +いずれにしても、同じ種類の内在する関数のラッパーを取得できます。JavaScript からみると、すべての wasm 関数は JavaScript 関数のようにみえます。しかし、これは wasm 関数オブジェクトインスタンスによってカプセル化されており、アクセスする方法は限られています。 + +## 例 + +物事を明らかにするために例を見ていきましょう(例は GitHub の [table-set.html](https://github.com/mdn/webassembly-examples/blob/master/other-examples/table-set.html) と [動作例](https://mdn.github.io/webassembly-examples/other-examples/table-set.html)、wasm の [テキスト表現](https://github.com/mdn/webassembly-examples/blob/master/ja-api-examples/table.wat) を参照してください): + +```js +var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 }); + +WebAssembly.instantiateStreaming(fetch('table.wasm')) +.then(function(obj) { + var tbl = obj.instances.exports.tbl; + console.log(tbl.get(0)()); // 13 + console.log(tbl.get(1)()); // 42 + otherTable.set(0,tbl.get(0)); + otherTable.set(1,tbl.get(1)); + console.log(otherTable.get(0)()); + console.log(otherTable.get(1)()); +}); +``` + +ここでは、{{jsxref("WebAssembly.Table")}} コンストラクタを使用して JavaScript からテーブル(`otherTable`)を作成し、{{jsxref("WebAssembly.instantiateStreaming()")}} ユーティリティ関数を使用して table.wasm をページに読み込みます。 + +そのあと、モジュールからエクスポートされた関数を取得し、関数の参照を [`tbl.get()`](/ja/docs/WebAssembly/API/Table/get) を通して取り出し、それぞれを実行した結果をコンソールに出力します。次に、 `set()` を使用して、`tbl` テーブルと同じ関数への参照を `otherTable` テーブルに含まれるようにします。 + +確認するために、`otherTable` から参照を取得し直し、その結果もコンソールに出力します(同じ結果が得られます)。 + +## それらは本当の関数です + +前の例で、[`Table.prototype.get()`](/ja/docs/WebAssembly/API/Table/get) のそれぞれの返り値はエクスポートされた WebAssembly 関数でした。まさに私達が話していたことです。 + +これらは WebAssembly 関数のラッパーであるのに加えて本当の JavaScript 関数 であることに注意してください。上の例を [WebAssembly をサポートするブラウザー](/ja/docs/WebAssembly#Browser_compatibility)でロードして、コンソール上で実行すると: + +```js +var testFunc = otherTable.get(0); +typeof testFunc; +``` + +結果として関数が返されます。この関数は他の JavaScript の他の [関数](/ja/docs/Web/JavaScript/Reference/Global_Objects/Function) と同じように扱うことができます(` call()、``bind()、その他 `)。`testFunc.toString()` は興味深い結果を返します: + +```js +function 0() { + [native code] +} +``` + +これはラッパー型の性質のアイデアの多くを提供します。 + +エクスポートされた WebAssembly 関数について他の注意事項は: + +- [length](/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/length) プロパティは wasm 内の関数シグネチャで宣言されている引数の数です。 +- [name](/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/name) プロパティは `toString()` の結果で見えている wasm モジュール内での関数のインデックスです。 +- i64 型の値を受け取る、または返すエクスポートされた wasm 関数を呼び出そうとすると、現在 JavaScript 上で i64 を表現する的確な方法がないためエラーをスローします。これは将来的に変わる可能性があります。新しい int64 型が将来の標準で検討されており、wasm によって使用される可能性があります。 diff --git a/files/ja/webassembly/index.html b/files/ja/webassembly/index.html deleted file mode 100644 index 497f89e062c027..00000000000000 --- a/files/ja/webassembly/index.html +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: WebAssembly -slug: WebAssembly -tags: - - Landing - - WebAssembly - - wasm -translation_of: WebAssembly ---- -
{{WebAssemblySidebar}}
- -

WebAssembly はモダンなウェブブラウザーで実行できる新しいタイプのコードです。ネイティブに近いパフォーマンスで動作するコンパクトなバイナリー形式の低レベルなアセンブリ風言語です。さらに、 C/C++ や Rust のような言語のコンパイル対象となって、それらの言語をウェブ上で実行することができます。 WebAssembly は JavaScript と並行して動作するように設計されているため、両方を連携させることができます。

- -

概要

- -

WebAssembly はウェブプラットフォームに大きな影響を与えます — 以前ではできなかったようなウェブ上で動作するクライアントアプリケーションのために、複数の言語で記述されたコードをウェブ上でネイティブに近いスピードで実行する方法を提供します。

- -

WebAssembly は JavaScript を補完、並行して動作するように設計されています — WebAssembly JavaScript API を使用して、 WebAssembly モジュールを JavaScript アプリケーションにロードし、2 つの間で機能を共有できます。これにより、WebAssembly コードの記述方法を知らなくても、 WebAssembly のパフォーマンスとパワー、JavaScript の表現力と柔軟性を同じアプリケーションで活用できます。

- -

さらに、W3C WebAssembly Working GroupCommunity Group を介して、ウェブ標準として開発されており、主要なブラウザーベンダーも積極的に参加しています。

- -
-
-

ガイド

- -
-
WebAssembly のコンセプト
-
まずは WebAssembly の高レベルなコンセプト— WebAssembly とはなにか、有用性、ウェブプラットフォーム (またはそれ以上) にどのように適合するか、どのように使用するか — の理解から始めてください。
-
C/C++ から WebAssembly にコンパイルする
-
C/C++ で書いたコードを Emscripten のようなツールを使って .wasm にコンパイルできます。どのように動作するか確認してみましょう。
-
既存の C モジュール から WebAssembly へのコンパイル
-
WebAssembly のコアユースケースは、既存のCライブラリのエコシステムを利用し、開発者が Web 上でそれらを使用できるようにすることです。
-
Rust から WebAssembly へのコンパイル
-
Rust コードを書いていれば、WebAssembly にコンパイルすることができます!このチュートリアルでは、Rust プロジェクトをコンパイルして既存の Web アプリケーションで使用するために知っておく必要があるすべてのことを説明します。
-
WebAssembly コードのロードと実行
-
.wasm を手に入れたら、この記事では、Fetch または XHR API と WebAssembly JavaScript API を組み合わせて、フェッチコンパイル、インスタンス化する方法について説明します。
-
WebAssembly JavaScript API の使用
-
.wasm モジュールをロードしたら、それを使いたいでしょう。この記事では、WebAssembly JavaScript API を用いて WebAssembly を使用する方法を説明します。
-
エクスポートされた WebAssembly 関数
-
エクスポートされた WebAssembly 関数は、WebAssembly 関数の JavaScript リフレクションであり、JavaScript から WebAssembly コードを呼び出すことができます。 この記事では、それらが何なのか説明します。
-
WebAssembly テキストフォーマットを理解する
-
この記事では wasm テキスト形式について説明します。これは .wasm モジュールの低レベルなテキスト表現で、デバッグ時にブラウザーの開発者ツールに表示されます。
-
WebAssembly テキストフォーマットから wasm に変換する
-
この記事では、テキスト形式で書かれた WebAssembly モジュールを .wasm バイナリに変換する方法について説明します。
-
-
- -
-

API リファレンス

- -
-
{{jsxref("Global_objects/WebAssembly", "WebAssembly")}}
-
このオブジェクトは、 WebAssembly に関連する全ての機能の名前空間として振る舞います。
-
{{jsxref("Global_objects/WebAssembly/Global", "WebAssembly.Global()")}}
-
WebAssembly.Global オブジェクトは JavaScript と1つ以上の {{jsxref("WebAssembly.Module")}} インスタンス(のインポート/エクスポート可能な値)を横断してアクセスできるグローバル変数のインスタンスを表現します。これによって、複数モジュールでの動的リンクを実現できます。
-
{{jsxref("Global_objects/WebAssembly/Module", "WebAssembly.Module()")}}
-
WebAssembly.Module オブジェクトにはブラウザーでコンパイルされたステートレスな WebAssembly コードが含まれており、効率的に Worker で共有したり、IndexedDB にキャッシュしたり、複数回インスタンス化したりすることができます。
-
{{jsxref("Global_objects/WebAssembly/Instance", "WebAssembly.Instance()")}}
-
WebAssembly.Instance オブジェクトはステートフルで、実行可能な Module のインスタンスです。Instance オブジェクトには JavaScript から WebAssembly コードを呼び出すことを許可されたエクスポートされた WebAssembly 関数が含まれます。
-
{{jsxref("Global_objects/WebAssembly/instantiateStreaming", "WebAssembly.instantiateStreaming()")}}
-
WebAssembly.instantiate() 関数は WebAssembly コードをコンパイル、インスタンス化するための主要な API で、Module と、その最初の Instance を返します。
-
{{jsxref("Global_objects/WebAssembly/Memory", "WebAssembly.Memory()")}}
-
WebAssembly.Memory オブジェクトはリサイズ可能な {{jsxref("Global_objects/ArrayBuffer", "ArrayBuffer")}} で、 Instance からアクセスされる生のバイト列を保持します。
-
{{jsxref("Global_objects/WebAssembly/Table", "WebAssembly.Table()")}}
-
WebAssembly.Table オブジェクトは Instance からアクセスされる関数参照などの不透明値のリサイズ可能な型付き配列です。
-
{{jsxref("WebAssembly.CompileError()")}}
-
WebAssembly CompileError オブジェクトを生成します。
-
{{jsxref("WebAssembly.LinkError()")}}
-
WebAssembly LinkError オブジェクトを生成します。
-
{{jsxref("WebAssembly.RuntimeError()")}}
-
WebAssembly RuntimeError オブジェクトを生成します。
-
-
-
- -

- - - -

仕様書

- - - - - - - - - - - - - - - - -
仕様書状態備考
{{SpecName('WebAssembly JS')}}{{Spec2('WebAssembly JS')}}JavaScript API の初回ドラフト定義。
- -

ブラウザーの互換性

- -

{{Compat("javascript.builtins.WebAssembly")}}

- -

関連情報

- - diff --git a/files/ja/webassembly/index.md b/files/ja/webassembly/index.md new file mode 100644 index 00000000000000..b41ab5696cea11 --- /dev/null +++ b/files/ja/webassembly/index.md @@ -0,0 +1,88 @@ +--- +title: WebAssembly +slug: WebAssembly +tags: + - Landing + - WebAssembly + - wasm +translation_of: WebAssembly +--- +{{WebAssemblySidebar}} + +WebAssembly はモダンなウェブブラウザーで実行できる新しいタイプのコードです。ネイティブに近いパフォーマンスで動作するコンパクトなバイナリー形式の低レベルなアセンブリ風言語です。さらに、 C/C++ や Rust のような言語のコンパイル対象となって、それらの言語をウェブ上で実行することができます。 WebAssembly は JavaScript と並行して動作するように設計されているため、両方を連携させることができます。 + +## 概要 + +WebAssembly はウェブプラットフォームに大きな影響を与えます — 以前ではできなかったようなウェブ上で動作するクライアントアプリケーションのために、複数の言語で記述されたコードをウェブ上でネイティブに近いスピードで実行する方法を提供します。 + +WebAssembly は JavaScript を補完、並行して動作するように設計されています — WebAssembly JavaScript API を使用して、 WebAssembly モジュールを JavaScript アプリケーションにロードし、2 つの間で機能を共有できます。これにより、WebAssembly コードの記述方法を知らなくても、 WebAssembly のパフォーマンスとパワー、JavaScript の表現力と柔軟性を同じアプリケーションで活用できます。 + +さらに、[W3C WebAssembly Working Group](https://www.w3.org/wasm/) と [Community Group](https://www.w3.org/community/webassembly/) を介して、ウェブ標準として開発されており、主要なブラウザーベンダーも積極的に参加しています。 + +## ガイド + +- [WebAssembly のコンセプト](/ja/docs/WebAssembly/Concepts) + - : まずは WebAssembly の高レベルなコンセプト— WebAssembly とはなにか、有用性、ウェブプラットフォーム (またはそれ以上) にどのように適合するか、どのように使用するか — の理解から始めてください。 +- [C/C++ から WebAssembly にコンパイルする](/ja/docs/WebAssembly/C_to_wasm) + - : C/C++ で書いたコードを[ Emscripten](/ja/docs/Mozilla/Projects/Emscripten/) のようなツールを使って .wasm にコンパイルできます。どのように動作するか確認してみましょう。 +- [既存の C モジュール から WebAssembly へのコンパイル](/ja/docs/WebAssembly/existing_C_to_wasm) + - : WebAssembly のコアユースケースは、既存の C ライブラリのエコシステムを利用し、開発者が Web 上でそれらを使用できるようにすることです。 +- [Rust から WebAssembly へのコンパイル](/ja/docs/WebAssembly/rust_to_wasm) + - : Rust コードを書いていれば、WebAssembly にコンパイルすることができます!このチュートリアルでは、Rust プロジェクトをコンパイルして既存の Web アプリケーションで使用するために知っておく必要があるすべてのことを説明します。 +- [WebAssembly コードのロードと実行](/ja/docs/WebAssembly/Loading_and_running) + - : .wasm を手に入れたら、この記事では、[Fetch](/ja/docs/Web/API/Fetch_API) または [XHR](/ja/docs/Web/API/XMLHttpRequest) API と [WebAssembly JavaScript](/ja/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) API を組み合わせて、フェッチコンパイル、インスタンス化する方法について説明します。 +- [WebAssembly JavaScript API の使用](/ja/docs/WebAssembly/Using_the_JavaScript_API) + - : .wasm モジュールをロードしたら、それを使いたいでしょう。この記事では、WebAssembly JavaScript API を用いて WebAssembly を使用する方法を説明します。 +- [エクスポートされた WebAssembly 関数](/ja/docs/WebAssembly/Exported_functions) + - : エクスポートされた WebAssembly 関数は、WebAssembly 関数の JavaScript リフレクションであり、JavaScript から WebAssembly コードを呼び出すことができます。 この記事では、それらが何なのか説明します。 +- [WebAssembly テキストフォーマットを理解する](/ja/docs/WebAssembly/Understanding_the_text_format) + - : この記事では wasm テキスト形式について説明します。これは .wasm モジュールの低レベルなテキスト表現で、デバッグ時にブラウザーの開発者ツールに表示されます。 +- [WebAssembly テキストフォーマットから wasm に変換する](/ja/docs/WebAssembly/Text_format_to_wasm) + - : この記事では、テキスト形式で書かれた WebAssembly モジュールを .wasm バイナリに変換する方法について説明します。 + +## API リファレンス + +- {{jsxref("Global_objects/WebAssembly", "WebAssembly")}} + - : このオブジェクトは、 WebAssembly に関連する全ての機能の名前空間として振る舞います。 +- {{jsxref("Global_objects/WebAssembly/Global", "WebAssembly.Global()")}} + - : `WebAssembly.Global` オブジェクトは JavaScript と 1 つ以上の {{jsxref("WebAssembly.Module")}} インスタンス(のインポート/エクスポート可能な値)を横断してアクセスできるグローバル変数のインスタンスを表現します。これによって、複数モジュールでの動的リンクを実現できます。 +- {{jsxref("Global_objects/WebAssembly/Module", "WebAssembly.Module()")}} + - : `WebAssembly.Module` オブジェクトにはブラウザーでコンパイルされたステートレスな WebAssembly コードが含まれており、効率的に [Worker で共有](/ja/docs/Web/API/Worker/postMessage)したり、[IndexedDB にキャッシュ](/ja/docs/WebAssembly/Caching_modules)したり、複数回インスタンス化したりすることができます。 +- {{jsxref("Global_objects/WebAssembly/Instance", "WebAssembly.Instance()")}} + - : `WebAssembly.Instance` オブジェクトはステートフルで、実行可能な `Module` のインスタンスです。`Instance` オブジェクトには JavaScript から WebAssembly コードを呼び出すことを許可された[エクスポートされた WebAssembly 関数](/ja/docs/WebAssembly/Exported_functions)が含まれます。 +- {{jsxref("Global_objects/WebAssembly/instantiateStreaming", "WebAssembly.instantiateStreaming()")}} + - : `WebAssembly.instantiate()` 関数は WebAssembly コードをコンパイル、インスタンス化するための主要な API で、`Module` と、その最初の `Instance` を返します。 +- {{jsxref("Global_objects/WebAssembly/Memory", "WebAssembly.Memory()")}} + - : `WebAssembly.Memory` オブジェクトはリサイズ可能な {{jsxref("Global_objects/ArrayBuffer", "ArrayBuffer")}} で、 `Instance` からアクセスされる生のバイト列を保持します。 +- {{jsxref("Global_objects/WebAssembly/Table", "WebAssembly.Table()")}} + - : `WebAssembly.Table` オブジェクトは `Instance` からアクセスされる関数参照などの不透明値のリサイズ可能な型付き配列です。 +- {{jsxref("WebAssembly.CompileError()")}} + - : WebAssembly `CompileError` オブジェクトを生成します。 +- {{jsxref("WebAssembly.LinkError()")}} + - : WebAssembly `LinkError` オブジェクトを生成します。 +- {{jsxref("WebAssembly.RuntimeError()")}} + - : WebAssembly `RuntimeError` オブジェクトを生成します。 + +## 例 + +- [WASMSobel](https://github.com/JasonWeathersby/WASMSobel) +- 他の多くの例については [webassembly-examples](https://github.com/mdn/webassembly-examples/) レポジトリーを参照してください。 + +## 仕様書 + +| 仕様書 | 状態 | 備考 | +| ---------------------------------------- | ------------------------------------ | ----------------------------------- | +| {{SpecName('WebAssembly JS')}} | {{Spec2('WebAssembly JS')}} | JavaScript API の初回ドラフト定義。 | + +## ブラウザーの互換性 + +{{Compat("javascript.builtins.WebAssembly")}} + +## 関連情報 + +- [WebAssembly on Mozilla Research](https://research.mozilla.org/webassembly/) +- [webassembly.org](http://webassembly.org/) +- [WebAssembly articles on Mozilla Hacks blog](https://hacks.mozilla.org/category/webassembly/) +- [W3C WebAssembly Community Group](https://www.w3.org/community/webassembly/) +- [Large-Allocation HTTP header](/ja/docs/Web/HTTP/Headers/Large-Allocation) +- [Emscripting a C Library to Wasm](https://developers.google.com/web/updates/2018/03/emscripting-a-c-library) diff --git a/files/ja/webassembly/loading_and_running/index.html b/files/ja/webassembly/loading_and_running/index.html deleted file mode 100644 index b105e5cdbf84c2..00000000000000 --- a/files/ja/webassembly/loading_and_running/index.html +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: WebAssemblyコードのロードと実行 -slug: WebAssembly/Loading_and_running -tags: - - Fetch - - JavaScript - - WebAssembly - - XMLHttpRequest - - バイトコード -translation_of: WebAssembly/Loading_and_running ---- -
{{WebAssemblySidebar}}
- -

JavaScript で WebAssembly を使用するには、まずコンパイル/インスタンス化の前にモジュールをメモリにプルする必要があります。この記事では、WebAssembly バイトコードをフェッチするために使用できるさまざまなメカニズムのリファレンスと、それをコンパイル/インスタンス化して実行する方法について説明します。

- -

どんな方法があるの?

- -

WebAssemblyは <script type='module'> または ES2015 の import 文とまだ統合されていないため、インポートを使用してブラウザでモジュールをフェッチする組み込みの方法はありません。

- -

以前の {{jsxref("WebAssembly.compile")}}/{{jsxref("WebAssembly.instantiate")}} メソッドでは、生のバイトをフェッチした後 WebAssembly モジュールのバイナリを含む {{domxref("ArrayBuffer")}} を作成し、コンパイル/インスタンス化する必要があります。これは文字列(JavaScript ソースコード) をバイトの配列バッファ (WebAssembly ソースコード)で置き換えることを除いて、new Function(string) に似ています。

- -

新しい {{jsxref("WebAssembly.compileStreaming")}}/{{jsxref("WebAssembly.instantiateStreaming")}} メソッドは、より効率的です。ネットワークからの生のバイトストリームに対して直接アクションを実行し、 {{domxref("ArrayBuffer")}} ステップの必要性がなくなりました。

- -

では、どのようにバイト列を配列バッファに読み込んでコンパイルするのでしょうか? 次の章で説明します。

- -

Fetchを使用する

- -

Fetch はネットワークリソースを取得するための便利でモダンな API です。

- -

wasm モジュールをフェッチする最も簡単で効率的な方法は、新しい {{jsxref("WebAssembly.instantiateStreaming()")}} メソッドを使用することです。このメソッドは最初の引数として fetch() を呼び出すことができ、1つのステップでフェッチ、モジュールをインスタンス化し、サーバからストリームされる生のバイトコードにアクセスします。

- -
WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)
-.then(results => {
-  // Do something with the results!
-});
- -

直接ストリームでは動作しない古い {{jsxref("WebAssembly.instantiate()")}} メソッドを使用した場合、フェッチされたバイトコードを {{domxref("ArrayBuffer")}} に変換する必要があります。次のようにです:

- -
fetch('module.wasm').then(response =>
-  response.arrayBuffer()
-).then(bytes =>
-  WebAssembly.instantiate(bytes, importObject)
-).then(results => {
-  // コンパイルされた結果(results)で何かする!
-});
- -

余談: instantiate() のオーバーロード

- -

{{jsxref("WebAssembly.instantiate()")}} 関数は2つのオーバーロードを持ちます — 1つ目 (上の例を参照)はバイトコードを受け取ってプロミスを返します。解決されたプロミスでコンパイルされたモジュールと、それをインスタンス化したものを含むオブジェクトとして受け取ります。オブジェクトの構造は以下のようになります:

- -
{
-  module : Module // コンパイルされた WebAssembly.Module オブジェクト,
-  instance : Instance // モジュールオブジェクトから生成された WebAssembly.Instance
-}
- -
-

: 通常はインスタンスのみを気にしますが、キャッシュする場合や、postMessage() を使用して別のワーカーやウィンドウと共有する場合や、インスタンスをさらに作成したい場合に備えて、モジュールを用意すると便利です。

-
- -
-

: 2番目のオーバーロードフォームは {{jsxref("WebAssembly.Module")}} オブジェクトを引数としてとり、結果としてインスタンスオブジェクトを直接含む Promise を返します。2番目のオーバーロードの例を参照してください。

-
- -

WebAssembly コードを実行する

- -

JavaScript 内で WebAssembly インスタンスが 有効になったら {{jsxref("WebAssembly.Instance/exports", "WebAssembly.Instance.exports")}} プロパティを通してエクスポートされた機能を使い始める事ができます。コードは以下のようになるでしょう:

- -
WebAssembly.instantiateStreaming(fetch('myModule.wasm'), importObject)
-.then(obj => {
-  // Call an exported function:
-  obj.instance.exports.exported_func();
-
-  // or access the buffer contents of an exported memory:
-  var i32 = new Uint32Array(obj.instance.exports.memory.buffer);
-
-  // or access the elements of an exported table:
-  var table = obj.instance.exports.table;
-  console.log(table.get(0)());
-})
- -
-

: WebAssembly モジュールからのエクスポートの仕組みの詳細については WebAssembly JavaScript API の使用WebAssemblyテキストフォーマットを理解する を参照してください。

-
- -

XMLHttpRequest を使用する

- -

XMLHttpRequest は Fetch よりやや古いですが、引き続き型付き配列を取得するために適切に使用することができます。繰り返しますが、モジュール名は simple.wasm とします:

- -
    -
  1. {{domxref("XMLHttpRequest()")}} インスタンスを生成して、{{domxref("XMLHttpRequest.open","open()")}} メソッドでリクエストをオープン、リクエストメソッドを GET に設定し、フェッチするためのパスを宣言します。
  2. -
  3. キーは {{domxref("XMLHttpRequest.responseType","responseType")}} を使用してレスポンスタイプを 'arraybuffer' にすることです。
  4. -
  5. 次に {{domxref("XMLHttpRequest.send()")}} を使用してリクエストします。
  6. -
  7. そのあと、ダウンロードが終了したときに {{domxref("XMLHttpRequest.onload", "onload")}} イベントハンドラから関数を実行します — この関数内で {{domxref("XMLHttpRequest.response", "response")}} プロパティから array buffer を取得し、Fetchで行ったように {{jsxref("WebAssembly.instantiate()")}} メソッドに渡します。
  8. -
- -

最終的なコードは以下のようになります:

- -
request = new XMLHttpRequest();
-request.open('GET', 'simple.wasm');
-request.responseType = 'arraybuffer';
-request.send();
-
-request.onload = function() {
-  var bytes = request.response;
-  WebAssembly.instantiate(bytes, importObject).then(results => {
-    results.instance.exports.exported_func();
-  });
-};
- -
-

: 動作例は xhr-wasm.html を参照してください。

-
diff --git a/files/ja/webassembly/loading_and_running/index.md b/files/ja/webassembly/loading_and_running/index.md new file mode 100644 index 00000000000000..500df1cc2bed1b --- /dev/null +++ b/files/ja/webassembly/loading_and_running/index.md @@ -0,0 +1,112 @@ +--- +title: WebAssemblyコードのロードと実行 +slug: WebAssembly/Loading_and_running +tags: + - Fetch + - JavaScript + - WebAssembly + - XMLHttpRequest + - バイトコード +translation_of: WebAssembly/Loading_and_running +--- +{{WebAssemblySidebar}} + +JavaScript で WebAssembly を使用するには、まずコンパイル/インスタンス化の前にモジュールをメモリにプルする必要があります。この記事では、WebAssembly バイトコードをフェッチするために使用できるさまざまなメカニズムのリファレンスと、それをコンパイル/インスタンス化して実行する方法について説明します。 + +## どんな方法があるの? + +WebAssembly は ` + + +``` + +このファイルのスクリプトは、js グルーコードをインポートし、wasm モジュールを初期化し、rust で書いた `greet` 関数を呼び出します。 + +プロジェクトのルートディレクトリに、ローカルのウェブサーバーを用意します(例: `python3 -m http.server` )。やり方がよくわからない場合は、[シンプルなローカル HTTP サーバーの実行](/ja/docs/Learn/Common_questions/set_up_a_local_testing_server#running_a_simple_local_http_server)を参考にしてください。 + +> **Note:** 必ず `application/wasm` という MIME 型に対応している最新のウェブサーバーを使用してください。古いウェブサーバーでは、まだ対応していないかもしれません。 + +ウェブサーバーから `index.html` を読み込む (Python3 の例を使用する場合: `http://localhost:8000`)。 画面上にアラートボックスが現れ、 `Hello, WebAssembly!` と表示されます。 JavaScript から Rust へ、そして Rust から JavaScript への呼び出しに成功しました。 + +## npm でパッケージが利用できるようにする + +WebAssembly モジュールを npm で使用する場合、いくつかの変更が必要です。 + +まず、Rust を target bundler オプションで再コンパイルすることから始めましょう。 + +```bash +$ wasm-pack build --target bundler +``` + +### Node.js と npm のインストール + +npmパッケージを構築しているので、Node.jsと npm をインストールしておく必要があります。 + +Node.js と npm を入手するには、 [Get npm!](https://docs.npmjs.com/getting-started/) ページへ移動して指示に従ってください。バージョンは好きなものを選んでください。このチュートリアルはバージョンを詳細に指定するものではありません。 + +次に、インストールした他の JavaScript パッケージがこのパッケージを利用できるようにするために、 \`npm link\` を使用しましょう。 + +```bash +$ cd pkg +$ npm link +``` + +Rust で書かれ、 WebAssembly にコンパイルされた npm パッケージができました。JavaScript から利用する準備ができており、ユーザーが Rust をインストールすることを必要としません。コードに含まれているのは WebAssembly コードであり、Rust のソースではないのです。 + +## パッケージのウェブでの利用 + +この新たなパッケージを利用するウェブサイトを構築しましょう。多くの人が様々なバンドラーツールで npm のパッケージを利用していますが、このチュートリアルではそのうちの一つである `webpack` を使用します。これは若干複雑ですが、現実的なユースケースを示します。 + +`pkg` ディレクトリーの外に戻り、新たなディレクトリー `site` を作成し、そこでこれを試してみましょう。 + +```bash +$ cd .. +$ mkdir site +$ cd site +$ npm link hello-wasm +``` + +新しいファイル `package.json` を作成し、次のコードをそこに書き込んでください。 + +```json +{ + "scripts": { + "serve": "webpack-dev-server" + }, + "dependencies": { + "hello-wasm": "^0.1.0" + }, + "devDependencies": { + "webpack": "^4.25.1", + "webpack-cli": "^3.1.2", + "webpack-dev-server": "^3.1.10" + } +} +``` + +次に、Webpack を設定する必要があります。`webpack.config.js` を作成し、そこに次のことを記入してください。 + +```js +const path = require('path'); +module.exports = { + entry: "./index.js", + output: { + path: path.resolve(__dirname, "dist"), + filename: "index.js", + }, + mode: "development" +}; +``` + +次に、HTML ファイルで参照される `index.js` を作成し、以下の内容を追加してください。 + +```js +import("./node_modules/hello-wasm/hello_wasm.js").then((js) => { + js.greet("WebAssembly with npm"); +}); +``` + +まこれは新しいモジュールを `node_modules` フォルダーからインポートします。これは最善の方法ではないと思いますが、デモなので、これでいいでしょう。一度そのモジュールが読み込まれると、そこから `greet` 関数を呼び出し、`"WebAssembly"` を文字列として渡します。ここに特別なことはなにもありませんが、Rust コードを呼び出していることに注意してください。JavaScript コードから観察する限り、これはただの普通のモジュールです。 + +最後に HTML ファイルが必要です。 `index.html` を作成し、次の内容を追加してください。 + +```html + + + + + hello-wasm example + + + + + +``` + +ファイルを作りました。これを試してみましょう。 + +```bash +$ npm install +$ npm run serve +``` + +これでウェブサーバーが起動します。 `http://localhost:8080` を読み込んでください。 `Hello, WebAssembly!` と書かれたアラートボックスが画面に出てくるはずです。JavaScript からの Rust の呼び出しと Rust からの JavaScript の呼び出しに成功しました。 + +## おわりに + +ここでチュートリアルは終わりです。あなたの役に立ったと思われることを望みます。 + +この領域にはたくさんの進行中の刺激的な仕事があります。もしそれをもっとよくするのを手伝いたいなら、 [the Rust WebAssembly Working Group](https://fitzgeraldnick.com/2018/02/27/wasm-domain-working-group.html) を確認してください。 diff --git a/files/ja/webassembly/text_format_to_wasm/index.html b/files/ja/webassembly/text_format_to_wasm/index.html deleted file mode 100644 index dd011ff444281b..00000000000000 --- a/files/ja/webassembly/text_format_to_wasm/index.html +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: WebAssembly テキストフォーマットから wasm に変換する -slug: WebAssembly/Text_format_to_wasm -tags: - - WebAssembly - - assembly - - conversion - - text format - - wabt - - wasm - - wast2wasm - - wat2wasm -translation_of: WebAssembly/Text_format_to_wasm ---- -

{{WebAssemblySidebar}}

- -

WebAssembly にはS式ベースのテキスト表現があります。これはテキストエディタ、ブラウザの開発者ツールなどで見せるために設計された中間表現です。この記事では、これがどのように動作するか、テキスト形式のファイルを .wasm アセンブリ形式に変換するのに利用可能なツールの使用方法について少し説明します。

- -
-

: テキスト形式のファイルは通常 .wat という拡張子で保存されます。場合によっては .wast も使われます。これはアサーションなどの変換時に .wasm に含まれない特別なテストコマンドを含むファイルを指します。

-
- -

はじめてのテキストフォーマット

- -

簡単な例を見てみましょう。次のプログラムは imports というモジュールから imported_func という名前の関数をインポートし、exported_func という名前の関数をエクスポートしています:

- -
(module
-  (func $i (import "imports" "imported_func") (param i32))
-  (func (export "exported_func")
-    i32.const 42
-    call $i
-  )
-)
- -

WebAssembly 関数 exported_func は私達の環境 (WebAssembly モジュールを使用しているウェブアプリケーションなど) で使用するためにエクスポートされます。この関数が呼び出されたとき、インポートされた JavaScript 関数 imported_func パラメータとして値 (42) を渡して実行されます。

- -

テキストの .wat ファイルからバイナリの .wasm ファイルに変換する

- -

上の .wat テキスト表現の例を .wasm アセンブリ形式に変換してみましょう。

- -
    -
  1. はじめに、上のコードをテキストファイルにコピーして simple.wat という名前のファイルを作成します。
  2. -
  3. このテキスト表現をブラウザが実際に読み込んで利用可能なアセンブリ言語にアセンブルする必要があります。 このために wabt ツールを使用することができます。これは WebAssembly のテキスト表現から wasm 変換する、または逆に変換するコンパイラ(加えてもう少し別のツール)が含まれます。https://github.com/webassembly/wabt に行って、そのページの説明に従ってツールの設定をします。
  4. -
  5. ツールをビルドしたら、システム PATH/wabt/out ディレクトリを追加します。
  6. -
  7. 次に、wast2wasm プログラムを実行します。入力ファイルパス、続いて -o パラメータ、出力ファイルパスを指定します: -
    wat2wasm simple.wat -o simple.wasm
    -
  8. -
- -

これで simple.wasm という名前のファイルに wasm が出力されます。これには .wasm アセンブリのコードが含まれます。

- -
-

: wasm2wat を使用して wasm から テキスト表現に戻すことができます。例: wasm2wat simple.wasm -o text.wat.

-
- -

アセンブリの出力を見る

- -

出力されたファイルはアセンブリベースなので通常のテキストエディタで表示することができません。ただし、wat2wasm ツールの -v オプションを使用して見ることができます。以下を試してみてください:

- -
wat2wasm simple.wat -v
- -

ターミナルには次のように出力されるでしょう:

- -

several strings of binary with textual descriptions beside them. For example: 0000008: 01 ; section code

- -

関連情報

- -
    -
  • WebAssembly テキストフォーマットを理解する — テキスト形式のシンタックスの詳細説明。
  • -
  • C/C++ から WebAssembly にコンパイルする — Binaryen/Emscripten のようなツールはソースコードを wasm にコンパイルし、JavaScript のコンテキストでモジュールを実行するために必要な API コードを作成します。それらの使用方法の詳細はこちらから探してください。
  • -
  • WebAssembly JavaScript API の使用 — WebAssembly API コードがどのように機能するかについて詳しく知りたい場合はこちらをお読みください。
  • -
  • Text format — WebAssembly GitHub レポジトリのテキスト形式の詳細説明。
  • -
  • wast-loader — あなたのためにこれをすべて処理する WebPack のローダーです。
  • -
diff --git a/files/ja/webassembly/text_format_to_wasm/index.md b/files/ja/webassembly/text_format_to_wasm/index.md new file mode 100644 index 00000000000000..bb635c57b97499 --- /dev/null +++ b/files/ja/webassembly/text_format_to_wasm/index.md @@ -0,0 +1,72 @@ +--- +title: WebAssembly テキストフォーマットから wasm に変換する +slug: WebAssembly/Text_format_to_wasm +tags: + - WebAssembly + - assembly + - conversion + - text format + - wabt + - wasm + - wast2wasm + - wat2wasm +translation_of: WebAssembly/Text_format_to_wasm +--- +{{WebAssemblySidebar}} + +WebAssembly には S 式ベースのテキスト表現があります。これはテキストエディタ、ブラウザの開発者ツールなどで見せるために設計された中間表現です。この記事では、これがどのように動作するか、テキスト形式のファイルを `.wasm` アセンブリ形式に変換するのに利用可能なツールの使用方法について少し説明します。 + +> **Note:** テキスト形式のファイルは通常 `.wat` という拡張子で保存されます。場合によっては `.wast` も使われます。これはアサーションなどの変換時に .wasm に含まれない特別なテストコマンドを含むファイルを指します。 + +## はじめてのテキストフォーマット + +簡単な例を見てみましょう。次のプログラムは `imports` というモジュールから `imported_func` という名前の関数をインポートし、`exported_func` という名前の関数をエクスポートしています: + +```wasm +(module + (func $i (import "imports" "imported_func") (param i32)) + (func (export "exported_func") + i32.const 42 + call $i + ) +) +``` + +WebAssembly 関数 `exported_func` は私達の環境 (WebAssembly モジュールを使用しているウェブアプリケーションなど) で使用するためにエクスポートされます。この関数が呼び出されたとき、インポートされた JavaScript 関数 `imported_func` パラメータとして値 (42) を渡して実行されます。 + +## テキストの .wat ファイルからバイナリの .wasm ファイルに変換する + +上の `.wat` テキスト表現の例を `.wasm` アセンブリ形式に変換してみましょう。 + +1. はじめに、上のコードをテキストファイルにコピーして `simple.wat` という名前のファイルを作成します。 +2. このテキスト表現をブラウザが実際に読み込んで利用可能なアセンブリ言語にアセンブルする必要があります。 このために wabt ツールを使用することができます。これは WebAssembly のテキスト表現から wasm 変換する、または逆に変換するコンパイラ(加えてもう少し別のツール)が含まれます。 に行って、そのページの説明に従ってツールの設定をします。 +3. ツールをビルドしたら、システム `PATH` に `/wabt/out` ディレクトリを追加します。 +4. 次に、wast2wasm プログラムを実行します。入力ファイルパス、続いて `-o` パラメータ、出力ファイルパスを指定します: + + ```bash + wat2wasm simple.wat -o simple.wasm + ``` + +これで `simple.wasm` という名前のファイルに wasm が出力されます。これには `.wasm` アセンブリのコードが含まれます。 + +> **Note:** wasm2wat を使用して wasm から テキスト表現に戻すことができます。例: `wasm2wat simple.wasm -o text.wat`. + +## アセンブリの出力を見る + +出力されたファイルはアセンブリベースなので通常のテキストエディタで表示することができません。ただし、wat2wasm ツールの `-v` オプションを使用して見ることができます。以下を試してみてください: + +```bash +wat2wasm simple.wat -v +``` + +ターミナルには次のように出力されるでしょう: + +![several strings of binary with textual descriptions beside them. For example: 0000008: 01 ; section code ](/en-US/docs/WebAssembly/Text_format_to_wasm/assembly-output.png) + +## 関連情報 + +- [WebAssembly テキストフォーマットを理解する](/ja/docs/WebAssembly/Understanding_the_text_format) — テキスト形式のシンタックスの詳細説明。 +- [C/C++ から WebAssembly にコンパイルする](/ja/docs/WebAssembly/C_to_wasm) — Binaryen/Emscripten のようなツールはソースコードを wasm にコンパイルし、JavaScript のコンテキストでモジュールを実行するために必要な API コードを作成します。それらの使用方法の詳細はこちらから探してください。 +- [WebAssembly JavaScript API の使用](/ja/docs/WebAssembly/Using_the_JavaScript_API) — WebAssembly API コードがどのように機能するかについて詳しく知りたい場合はこちらをお読みください。 +- [Text format](https://webassembly.github.io/spec/core/text/index.html) — WebAssembly GitHub レポジトリのテキスト形式の詳細説明。 +- [wast-loader](https://github.com/xtuc/webassemblyjs/tree/master/packages/wast-loader) — あなたのためにこれをすべて処理する WebPack のローダーです。