関連する投稿
Node.js + nobleを使ってMicrobitのセンサー情報を読み取る
Node.jsのモジュールをC++で作成する(その2)
dualshock3の入力情報を独自のC++コードで作成している。Bluetooth通信でMicrobit側の情報はNode.jsとnobleモジュールで何とか成りそうなので、あとはこのdualshock側のC++コードをどうにかNode.jsで利用できれば、連携できそう。
ということで、Node.jsモジュールをC++コードで作成できるようなる必要がある。ただし、このアドオンはバージョンが上がるたびに仕様がコロコロ変わるらしい。最新版のドキュメントは以下にあるので、まずこれをビルドしてみる。
node-gyp
というビルドツールが必要なので、インストールする。npmでモジュールをダウンロードするときにプラットフォームごとにビルドが実行されることがよくあるが、この時にモジュールを作成しているツールがこれになる。念のため最新版を入れておいたほうが良い。
> npm install -g node-gyp
とりあえずaddontest
というフォルダを作成してその中で作業する。
> mkdir addontest
> cd addontest
必要なのは、C++のソースファイル(hello.cc)とビルドの設定ファイルとなるbinding.gyp
を用意する必要がある。最近はいろんな形式でモジュール用プログラムを記述できるようだが、情報が多いv8形式
で作成する。
よくわからない記述だらけだが、カスタマイズが必要なのは以下の場合、void Method(const FunctionCallbackInfo<Value>& args)
だけである。今回Methodという名称で作成したが、なんでも良い。最後にjavascriptからコールするときのfunction名と実際に呼び出される関数の紐づけを、NODE_SET_METHOD(exports, "hello", Method);
でやっている。ほかはお約束コードのようなものだと割り切っている。
> vi hello.cc
// hello.cc
#include <node.h>
namespace demo {
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
}
void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "hello", Method);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, init)
}
ビルドの設定ファイル。ソースはどれなのか、作成するモジュール名をどうするのかを以下のように記載する。
// binding.gyp
{
"targets": [
{
"target_name": "addon",
"sources": [ "hello.cc" ]
}
]
}
最後にnode-gyp
を実行する。第2引数の名称でサブフォルダを指定すると、その中にモジュールが作成される。
> node-gyp configure build
gyp info it worked if it ends with ok
gyp info using node-gyp@3.6.2
gyp info using node@8.10.0 | linux | x64
gyp info spawn /usr/bin/python2
gyp info spawn args [ '/usr/local/node-v6.11.4/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args '/home/hoge/work/addontest/modules/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args '/usr/local/node-v6.11.4/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/home/hoge/.node-gyp/8.10.0/include/node/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/home/hoge/.node-gyp/8.10.0',
gyp info spawn args '-Dnode_gyp_dir=/usr/local/node-v6.11.4/lib/node_modules/node-gyp',
gyp info spawn args '-Dnode_lib_file=/home/hoge/.node-gyp/8.10.0/<(target_arch)/node.lib',
gyp info spawn args '-Dmodule_root_dir=/home/hoge/work/addontest/modules',
gyp info spawn args '-Dnode_engine=v8',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.' ]
make: ディレクトリ '/home/hoge/work/addontest/modules/build' に入ります
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
CXX(target) Release/obj.target/addon/hello.o
SOLINK_MODULE(target) Release/obj.target/addon.node
COPY Release/addon.node
make: ディレクトリ '/home/hoge/work/addontest/modules/build' から出ます
gyp info ok
hoge@ubuntu:~/work/addontest/modules$
上記のようにモジュールを作成すると、javascript側では以下のようにコールすることができる。
> vi hello.js
const addon = require('./build/Release/addon');
console.log(addon.hello());
実際に実行した結果が以下になる。
> node hello.js
world