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

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

v8はC言語のライブラリをNode.jsと接続することが出来るライブラリです。
Raspberry PiがJessieからStrechにバージョンアップして、Node.jsのバージョンが0.12系から4.8.6に上がり、C++アドオンであるv8の仕様も大幅に変わりました。

C++アドオンを一つのファイルでJessieとStrechの両方に対応したいと思っていたらできましたので、そのやり方を解説します。

開発したソースコードは[こちら](https://github.com/LAPIS-Lazurite/node-red-contrib-lazurite/blob/master/nodes/lazurite/lazurite_wrap.cc)にある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); |
|配列 | Local<Array>packet_array = Array::New(isolate); | Local<Array>packet_array = Array::New() |
| JSON | Local<Object> obj = Object::New(isolate); |Local<Object> 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)
```