Node.jsのモジュールをC++で書く (ObjectとArrayを受け取るメソッド)
プリミティブな値を引数で受けとる場合よりもやや面倒。JavaScriptの仕様上どんな値や型でも受けとってしまうので、C++側のチェックコードがどんどん増えていく。
動作確認用のコードがこうだとする
var Test1 = require('./build/Release/Test1'); Test1.giveMeObject({ option1: 'This is config option!!', option2: true }); Test1.giveMeArray([1,2,3,4,5,6]);
モジュールのコードはこんな感じ
#include <node.h> #include <v8.h> #include <iostream> using namespace v8; Handle<Value> HandleObjectMethod(const Arguments& args) { HandleScope scope; // 第一引数の型がObjectかどうかをチェック if (!args[0]->IsObject()) { Local<String> msg = String::New("Argument must be Object type"); ThrowException(Exception::TypeError(msg)); return scope.Close(Undefined()); } // v8::Object型にキャスト Local<Object> obj = Local<Object>::Cast(args[0]); std::string strOption1 = ""; bool bOption2 = ""; { // Check Option1 Local<Value> v = obj->Get(String::New("option1")); if (v.IsEmpty() || !v->IsString()) { Local<String> msg = String::New("Option1 is not specified or invalid type"); ThrowException(Exception::TypeError(msg)); return scope.Close(Undefined()); } else { int length = v->ToString()->Length(); char c[length]; v->ToString()->WriteAscii(c); strOption1 += c; } } std::cout << "Option1 = " << strOption1 << std::endl; { // Check Option2 Local<Value> v = obj->Get(String::New("option2")); if (v.IsEmpty() || !v->IsBoolean()) { Local<String> msg = String::New("Option2 is not specified or invalid type"); ThrowException(Exception::TypeError(msg)); return scope.Close(Undefined()); } else { bOption2 = v->ToBoolean()->Value(); } } std::cout << "Option2 = " << bOption2 << std::endl; return scope.Close(Boolean::New(true)); } Handle<Value> HandleArrayMethod(const Arguments& args) { HandleScope scope; // 第一引数の型がArrayかどうかのチェック if (!args[0]->IsArray()) { Local<String> msg = String::New("Argument must be Array type"); ThrowException(Exception::TypeError(msg)); return scope.Close(Undefined()); } // v8::Arrayにキャスト Local<Array> arr = Local<Array>::Cast(args[0]); int length = arr->Length(); std::cout << "Length:" << length << std::endl; for (int i = 0; i < length; i++) { // Arrayの各要素にアクセス Local<Value> v = arr->Get(i); // Something todo } return scope.Close(v8::Boolean::New(true)); } void init(Handle<Object> target) { // メソッドのexport target->Set(String::NewSymbol("giveMeObject"), FunctionTemplate::New(HandleObjectMethod)->GetFunction()); target->Set(String::NewSymbol("giveMeArray"), FunctionTemplate::New(HandleArrayMethod)->GetFunction()); } NODE_MODULE(Test1, init)
実行結果
Option1 = This is config option!!
Option2 = 1
Length:6