Posted at

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)