Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
21
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

node v8.0.0でWebAssembly試してみる

概要

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にして埋め込むしかないのかな?)。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
21
Help us understand the problem. What are the problem?