まず、nodeからネイティブモジュールを叩くには、node-ffiを使用します。
node-ffiですが、nodeのバージョンが0.10から0.12になるにかけて、ネイティブモジュールに関係する部分で後方互換性が失われてしまうという事件が起こっています。
現状0.11や0.12で動かすことは不可能ではないですが、私は落ち着いてから試すことにしました。
詳しい内容は、"NAN node"とかでググるか以下の記事をみるといいかもしれません。
今回は、このへんの話には、触れないでv0.10系を使うことにします。
環境
- Ubuntu 14.10 (x64)
OSXでも同じようにできる気がします。
nw.jsのインストール
npmで古いnwをインストールできなかったので、tarを落とします。
OSに合わせてnw@0.8.6をダウンロードします。
ネイティブモジュールの後方互換性のために、nodeのv0.10系を使用している、v0.8系もメンテされているようです。
nw@0.8.6は、node@0.10.22/Chrome@30.0.1599.66です。
配置
まず、nvmで0.10.22をインストールします。(v.10でもいいかもしれません)
$ nvm install v0.10.22
サンプルを作成するために、お好みでディレクトリを掘って、package.jsonを作成します(npm init)
$ mkdir path/to/dir
$ cd path/to/dir
$ npm init
(index.jsの部分を、index.htmlにする、ほかはEnter)
node-ffiもインストールしておきます。
$ npm install -save ffi
さっきダウンロードしたnwを解凍して、node_modulesに配置しておきます(nwコマンドを叩くだけなので、別にどこでもいいです。)
$ mv path/to/node-webkit-v0.8.6-linux-x64 ./node_modules
Linux系OSの場合のエラー
nwを実行すると、多分次のエラーが出ます。
error while loading shared libraries: libudev.so.0: cannot open shared object file: No such file or directory
それについては、ドキュメントでも言及されているので参考にします。
The solution of lacking libudev.so.0 · nwjs/nw.js Wiki
バイナリを書き換えてしまうのが手軽そうなのでそうします(他の方法もあります)
$ cd node_modules/node-webkit-v0.8.6-linux-x64
$ sed -i 's/udev\.so\.0/udev.so.1/g' nw
node-ffiのビルド
nw@0.8.6向けにnode-ffiをリビルドします。
nodeのネイティブアドオンのビルドには、node-gypを使いますが、nw向けに便利化されたnw-gypがあるのでそちらを使います。
nw-gypをグローバルにインストールします。
$ npm install -g nw-gyp
nw-gypを使ってnode-ffiをリビルドします。targetには今回使用するnw.jsのバージョン(0.8.6)を指定します。
$ cd node_modules/ffi
$ nw-gyp rebuild --target=0.8.6
ffiの依存関係で入っている"ref"もリビルドします。
$ cd node_modules/ffi/node_modules/ref
$ nw-gyp rebuild --target=0.8.6
さらに、依存関係で入っている"ref-struct"の依存関係で入っている"ref"もリビルドします。
$ cd node_modules/ffi/node_modules/ref-struct/node_modules/ref
$ nw-gyp rebuild --target=0.8.6
これら全部をビルドしないと、以下のようなエラーが出るはずです。
...(略)...
undefined symbol: _ZN2v86String3NewEPKci
サンプルを動かしてみる
node-ffiのREADMEでlibmを動かしているの、同じように使えるか試してみます。
<!DOCTYPE html>
<html>
<head>
<title>Hello FFI!</title>
</head>
<body>
<h1>Hello FFI!</h1>
<script>
var ffi = require("ffi");
var math = ffi.Library('libm', {
'sqrt': [ 'double', [ 'double' ] ]
});
var x = math.sqrt(2); // sqrt(2)=1.4142135623730951
document.write(x.toString());
</script>
</body>
</html>
nwを起動すると、√2が表示されるはずです。
$ ./node_modules/node-webkit-v0.8.6-linux-x64/nw .
おお、ffi使えてます。
まとめ
依存関係のrefまでリビルドしないといけないのに気づくのに少し時間がかかりましたが、nwでもffi動くようです。
調べていると、解決していないパターン(How to use node-ffi in node-webkit? · Issue #138 · node-ffi/node-ffi)が多くて困りました。
以下のサンプルも動かせそうですが、gruntとかを使ってて構成が少し複雑そうだったので試してません。