C言語によるNode.jsのモジュール開発 v8のまとめ
v8はC言語のライブラリをNode.jsと接続することが出来るライブラリです。
Raspberry PiがJessieからStrechにバージョンアップして、Node.jsのバージョンが0.12系から4.8.6に上がり、C++アドオンであるv8の仕様も大幅に変わりました。
C++アドオンを一つのファイルでJessieとStrechの両方に対応したいと思っていたらできましたので、そのやり方を解説します。
開発したソースコードはこちらにあるlazurite_wrap.ccです。
この中を部分的に切り出して差異の説明をします。
バージョンを取得する
33行目あたり...
V8_MAJOR_VERSIONでバージョンを取得できます。
JessieはV8_MAJOR_VERSIONがありませんので、#elseでV8_VER_0を宣言して、Versionが4のときとVersionが5のときに、V8_VER_5を宣言しています。
以降、ソースコードの本体ではV8_VER_0とV8_VER_5でバージョンを識別していきます。
#include <v8.h>
#include "liblazurite.h"
#if (V8_MAJOR_VERSION == 4)
#define V8_VER_5
#elif (V8_MAJOR_VERSION == 5)
#define V8_VER_5
#else
#define V8_VER_0
#endif
関数の宣言
関数の宣言部分はこのように異なります。
戻り値の指定方法と、引数を取得するargsの宣言が両方共異なります。
#ifdef V8_VER_0
static Handle<Value> dlopen(const Arguments& args) {
HandleScope scope;
#endif
#ifdef V8_VER_5
static void dlopen(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
#endif
Nodeに渡す変数の生成
isolateの引数が追加になっています。
また、文字列の宣言が変わっています。
(補足) strはchar*です。string型ではありません。
データ型 | v4系 | V0系 |
---|---|---|
文字列 | String::NewFromUtf8(isolate,str); | String::New(str) |
Integer型 | Integer::New(isolate,int_data); | Integer::New(int_data); |
Boolean型 | Boolean::New(isolate,bool_data); | Boolean::New(bool_data); |
uint32_t型 | Uint32::New(isolate,uint32_data); | Uint32::New(uint32_data); |
配列 | Localpacket_array = Array::New(isolate); | Localpacket_array = Array::New() |
JSON | Local obj = Object::New(isolate); | Local obj = Object::New(); |
引数の取得
それぞれ引数が順番に、以下のように指定されているとします。
args[0] 小数点を含む数値
args[1] Boolean
args[2] Integer
args[3] 文字列
args[3] 配列
これらの値を取り出す方法は値を取得する方法は次のとおりです。
これは、バージョンによる違いはありません。
double double_data = args[0]->NumberValue();
bool bool_data = args[1]->BooleanValue();
int int_data = args[2]->IntegerValue();
String::Utf8Value str(args[3]->ToString());
Local<Array> arr = Local<Array>::Cast(args[4]);
戻り値
戻り値の返し方は大きく異なります。
v0.12系はreturnで返すのに対して、v4.8.6ではargsにセットして関数を抜けます。
また、戻り値をセットするときに、isolateの引数が追加になっています。
#ifdef V8_VER_0
return scope.Close(Boolean::New(true));
#endif
#ifdef V8_VER_5
args.GetReturnValue().Set(Boolean::New(isolate,true));
return;
#endif
}
JSONオブジェクトの作成方法
JSONのkeyの宣言方法が異なっています。
#ifdef V8_VER_0
Local<Object> obj = Object::New();
obj->Set(String::NewSymbol("payload"),String::New(str));
#endif
#ifdef V8_VER_5
Local<Object> obj = Object::New(isolate);
obj->Set(String::NewFromUtf8(isolate,"payload"),String::NewFromUtf8(isolate,str));
#endif
Nodeから見える関数の宣言
初期化関数の宣言部分のみが異なります。
#ifdef V8_VER_0
static void Init(Handle<Object> target) {
#endif
#ifdef V8_VER_5
static void Init(Local<Object> target) {
target->GetIsolate();
#endif
NODE_SET_METHOD(target, "dlopen", dlopen);
NODE_SET_METHOD(target, "init", init);
..... 省略 .....
NODE_SET_METHOD(target, "remove", remove);
NODE_SET_METHOD(target, "dlclose", dlclose);
}
NODE_MODULE(lazurite_wrap, Init)