LoginSignup
43
20

More than 5 years have passed since last update.

node v8.0.0でWebAssembly試してみる

Last updated at Posted at 2017-05-31

概要

node v8.0.0 がリリースされました。このバージョンからWebAssemblyがデフォルトで使用できるようになったので、試しにnode module(re2のvalidateするだけ)を作ってみました(re2-validator)。

準備

submoduleにre2を引っ張ってきてre2をconfigure makeします。

$ cd re2
$ emconfigure ./configure
$ make

コンパイル

emccで普通にコンパイルします。

$ emcc -Ire2 --bind -o dist/re2.js  re2_binding.cc re2/obj/libre2.a -s WASM=1 --llvm-lto 1 --llvm-opts 3 -s NO_FILESYSTEM=1  -s EXPORTED_RUNTIME_METHODS="[]" --closure 1 -Oz --pre-js pre.js --post-js post.js

ここでre2本体以外にre2_binding.cc、pre.js、post.jsという自作のファイルを使用しています。それぞれ説明すると、

re2_binding.ccで関数をModule._validateから使えるようにします。

re2_binding.cc
#include "re2/re2/re2.h"
#include <emscripten/bind.h>

using namespace emscripten;
using std::string;

bool validate(const string& str) {
  RE2 re(str, RE2::Quiet);
  return re.ok();
}

EMSCRIPTEN_BINDINGS(_re2_) {
  function("_validate", &validate);
}

pre.jsでModule.wasmBinaryFileを設定して、正しいパスを指すようにします。これをやらないとパスがずれます。

pre.js
var Module = {};
if (typeof __dirname === "string") Module["wasmBinaryFile"] = __dirname + "/re2.wasm";

post.jsで実際にJavaScriptから使いやすいように加工します(emccからclosure compilerのオプションを設定する方法がわからなかったので、es5的な感じで)。validate関数で文字列をutf8のUint8Arrayに変換してModule._validateに渡します。readyModule._validateの準備が完了するまで待つPromiseです。emscripten内部ではWebAssembly.instantiateを使用して非同期にwasmモジュールがコンパイル、インスタンス化されるので必要です(対話環境だったら、あんまり気にしないですけどね)。

post.js
var re2_buffer = new Uint8Array(1024);

module.exports['validate'] = function(s) {
  var size = stringToUTF8Array(s, re2_buffer, 0, 1024);
  return Module['_validate'](re2_buffer.subarray(0, size));
};

module.exports['ready'] = new Promise(function(resolve) {
  var intervalId = setInterval(function() {
    if (!Module['_validate']) return;
    clearInterval(intervalId);
    resolve();
  }, 1);
});

動作確認してみます。

$ node
> var re2Validator = require('./dist/re2');
> re2Validator.validate('(?!hello)'); // false

publishしたライブラリを使用する

すでに、node moduleとしてpublishしたものとします。npm iして、まぁ、動作確認でやったことなんですが、動かしてみます。

$ npm i --no-save @ukyo/re2-validator
$ node
> var re2Validator = require('@ukyo/re2-validator');
> re2Validator.validate('(?!hello)'); // false

これでWebAssemblyを使用したnode moduleを公開できましたね!

まとめ

node v8.0.0で動作する、WebAssemblyを使用したnode moduleを作ってみました。node環境では特に問題なく動くことが確認できました。ブラウザ環境でwasmのパスどうするんだっていう課題はありますね(wasmを配列とかbase64にして埋め込むしかないのかな?)。

43
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
20