WebAssembly-「HelloWorld」

この章では、Cで簡単なプログラムを作成し、それを.wasmに変換し、ブラウザーで同じように実行して、「HelloWorld」というテキストを取得します。

Cプログラムを.wasmに変換し、.htmlファイル内の.wasmを利用するwasmエクスプローラーツールを利用します。

で利用可能なWasmエクスプローラーツール https://mbebenita.github.io/WasmExplorer/ looks as follows −

使用するCコードは次のとおりです。

#include <stdio.h>
char *c_hello() {
   return "Hello World"; 
}

以下に示すように、wasmexplorerの最初のブロックをCコードで更新します-

以下に示すように、COMPILEボタンをクリックして、WASM、WAT、およびFirefox x86Webアセンブリにコンパイルします。

ダウンロードを使用して.wasmファイルを取得し、名前を付けて保存します firstprog.wasm

以下に示すように、firstprog.htmlという.htmlファイルを作成します-

<!doctype html>
<html>
   <head>
      <meta charset="utf-8"> 
      <title>WebAssembly Hello World</title> 
   </head> 
   <body>
      <div id="textcontent"></div>     
      <script type="text/javascript"> 
         //Your code from webassembly here
      </script> 
   </body>
</html>

ここで、firstprog.wasmを使用して、C関数c_hello()からhelloworldを読み取ります。

ステップ1

fetch()apiを使用して、firstprog.wasmコードを読み取ります。

ステップ2

.wasmコードは、を使用してarraybufferに変換する必要があります ArrayBuffer。ArrayBufferオブジェクトは、固定長のバイナリデータバッファを返します。

これまでのコードは次のようになります-

<script type="text/javascript"> 
   fetch("firstprog.wasm") .then(bytes => bytes.arrayBuffer()) 
</script>

ステップ3

ArrayBufferからのバイトは、を使用してモジュールにコンパイルする必要があります WebAssembly.compile(buffer) 関数。

コードは次のようになります-

<script type="text/javascript">
   fetch("firstprog.wasm")
   .then(bytes => bytes.arrayBuffer())
   .then(mod => WebAssembly.compile(mod))
</script>

ステップ4

モジュールを取得するには、以下に示すようにwebassembly.instanceコンストラクターを呼び出す必要があります-

<script type="text/javascript">     
   fetch("firstprog.wasm") 
   .then(bytes => bytes.arrayBuffer())
   .then(mod => WebAssembly.compile(mod))
   .then(module => {return new WebAssembly.Instance(module) }) 
</script>

ステップ5

インスタンスをコンソールして、ブラウザで詳細を確認しましょう。

<script type="text/javascript"> 
   fetch("firstprog.wasm") .then(bytes => bytes.arrayBuffer()) 
   .then(mod => WebAssembly.compile(mod)) .then(module => {
      return new WebAssembly.Instance(module) 
   }) 
   .then(instance => {
      console.log(instance);
   }); 
</script>

console.logの詳細を以下に示します-

関数c_hello()から文字列「HelloWorld」を取得するには、javascriptにコードを追加する必要があります。

まず、以下に示すようにメモリバッファの詳細を取得します-

let buffer = instance.exports.memory.buffer;;

バッファ値から値を読み取ることができるように、バッファ値を型付き配列に変換する必要があります。バッファーには、文字列HelloWorldが含まれています。

型付きに変換するには、以下に示すようにコンストラクターUint8Arrayを呼び出します-

let buffer = new Uint8Array(instance.exports.memory.buffer);

これで、forループでバッファーから値を読み取ることができます。

以下に示すように作成した関数を呼び出して、バッファーを読み取るための開始点を取得しましょう。

let test = instance.exports.c_hello();

これで、テスト変数に文字列を読み取るための開始点があります。WebAssemblyには文字列値用のものはなく、すべてが整数として格納されます。

したがって、バッファから値を読み取ると、それらは整数値になり、JavaScriptのfromCharCode()を使用して文字列に変換する必要があります。

コードは次のとおりです-

let mytext = ""; 
for (let i=test; buffer[i]; i++){ 
   mytext += String.fromCharCode(buffer[i]);
}

これで、mytextをコンソールすると、「HelloWorld」という文字列が表示されます。

完全なコードは次のとおりです-

<!doctype html> 
<html> 
   <head> 
      <meta charset="utf-8"> 
      <title>WebAssembly Add Function</title>
      <style>
         div { 
            font-size : 30px; text-align : center; color:orange; 
         } 
      </style>
   </head>
   <body>
      <div id="textcontent"></div>
      <script> 
         fetch("firstprog.wasm")
         .then(bytes => bytes.arrayBuffer())
         .then(mod => WebAssembly.compile(mod))
         .then(module => {return new WebAssembly.Instance(module)})
         .then(instance => {   
            console.log(instance); 
            let buffer = new Uint8Array(instance.exports.memory.buffer); 
            let test = instance.exports.c_hello(); 
            let mytext = ""; 
            for (let i=test; buffer[i]; i++) {
               mytext += String.fromCharCode(buffer[i]);
            }
            console.log(mytext); document.getElementById("textcontent").innerHTML = mytext; 
         });
      </script>
   </body>
</html>

divを追加し、コンテンツをdivに追加したので、文字列がブラウザに表示されます。

出力

出力は以下に記載されています-