C
C++
Node.js
v8
node-red

C言語によるNode.jsのモジュール開発 v8のまとめ

More than 1 year has passed since last update.

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でバージョンを識別していきます。

lazurite_wrap.cc
#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の宣言が両方共異なります。

lazurite_wrap.cc
#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] 配列

これらの値を取り出す方法は値を取得する方法は次のとおりです。
これは、バージョンによる違いはありません。

lazurite_wrap.cc
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の引数が追加になっています。

lazurite_wrap.cc
#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の宣言方法が異なっています。

lazurite_wrap.cc
#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から見える関数の宣言

初期化関数の宣言部分のみが異なります。

lazurite_wrap.cc
#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)