ushumpei’s blog

生活で気になったことを随時調べて書いていきます。

WebAssembly って?

ブラウザからアセンブリ言語を実行できる仕組みが WebAssembly という理解です (雑魚)。

とりあえず、動かしてみます。

Emscripten

C/C++ から WebAssembly で実行可能なアセンブリコンパイルするツールだそうです。C/C++ に特に思い入れはなく、仕事で使ったことはないですが、例えば C/C++ で書かれたライブラリを JavaScript ライブラリに変換するとかできるのかなーと思います。

C/C++からWebAssemblyにコンパイルする を参考に emscripten をインストールします。(すっごい時間かかりますね)

使う

適当な cpp ファイル (main.cpp) を作成します (これ c といってもいいのでは)

#include <stdio.h>
#include <emscripten/emscripten.h>

extern "C" {
  int main()
  {
    puts("Hello, World");
  }

  int myFunction(int x)
  {
    return ++x;
  }
}

em++ main.cpp -s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall']" -s EXPORTED_FUNCTIONS="['_main', '_myFunction']" を実行します。ここでは

  • クライアント側から関数を呼び出す Module.ccall を使用するために EXTRA_EXPORTED_RUNTIME_METHODSccall を指定します。
  • 呼び出せる関数を EXPORTED_FUNCTIONS で指定します。関数名に _ プレフィックスをつけなければいけないそうです。

以下のファイルが生成されました。

  • a.out.js
  • a.out.wasm
  • main.cpp

index.html を作成してそこから a.out.js を読み込みます。

<html>
  <head>
    <script src="a.out.js"></script>
    <script>
      function callMyFunction() {
        var count = document.getElementById('count')
        var nextCount = Module.ccall('myFunction', 'number', ['number'], [count.innerText])
        count.innerText = nextCount
      }
    </script>
  </head>
  <body>
    <p>Count: <span id="count">0</span></p>
    <button onclick="callMyFunction()">Call C++ Function</button>
  </body>
</html>

しかしこれでは動きません。http 経由で配信しなければいけないそうです。express で配信するようにします。yarn init && yarn add express でサーバーを準備します。index.js を以下のように記述しました。

var express = require('express');
var app = express();

app.use(express.static('public'));

app.get('/', function(req, res) {
  res.sendFile(__dirname + '/public/hello.html');
});

app.listen(3000);

またディレクトリ構造を少し変えます。コンパイルしたものは public 以下に放置しています。

.
├── index.js
├── node_modules
├── package.json
├── public
│   ├── a.out.js
│   ├── a.out.wasm
│   ├── index.html
│   └── main.cpp
└── yarn.lock

サーバーを node index.js で起動すると localhost:3000 でアクセスできるようになます。

f:id:ushumpei:20180619104114g:plain

感想

また何かに入門だけしているやつです