V8 JavaScriptエンジン - オブジェクトの追加
Rev.1を表示中。最新版はこちら。
V8 JavaScriptエンジンの組み込み - オブジェクトの追加
V8 JavaScriptエンジン - 変数の追加の続き。今度は、グローバル領域へオブジェクト({}リテラルで定義するもの)を追加してみる。追加するオブジェクトは以下のとおり。
オブジェクト名:LunchTime
内容:時、分の二つの値を格納するオブジェクト。
プロパティ:
- hour
- min
オブジェクトを追加する場合は、専用のオブジェクトテンプレートを一つ作成(下記ソースではtime_templ)し、そこにプロパティ名とアクセサを登録する。そして、作成したオブジェクトテンプレートをglobal領域用のオブジェクトテンプレートにオブジェクト名(下記ソースではLunchTime)と関連づけて登録する。各プロパティのアクセサ(set/get_hour(),set/get_min())では、
#include <v8.h> #include <iostream> #include <string> using namespace v8; static void read_file(std::istream& ifs, std::string &content) { content = ""; std::string t; while (!ifs.eof()) { getline(std::cin, t); content += t + "\n"; } } // log()が呼ばれた時のコールバックルーチン static Handle<Value> log_callback(const Arguments& args) { if (args.Length() < 1) return v8::Undefined(); HandleScope scope; Handle<Value> arg = args[0]; String::Utf8Value value(arg); std::cout << "log: " << *value << std::endl; return v8::Undefined(); } // 追加するオブジェクトに対応するclass class Time { public: Time() : hour(0), min(0) {} int hour; int min; }; // オブジェクトのプロパティのアクセサ Handle<Value> get_hour(Local<String> property, const AccessorInfo &info) { Local<Object> self = info.Holder(); Local<External> wrap = Local<External>::Cast(self->GetInternalField(0)); void* ptr = wrap->Value(); int value = static_cast<Time*>(ptr)->hour; return Integer::New(value); } void set_hour(Local<String> property, Local<Value> value, const AccessorInfo& info) { Local<Object> self = info.Holder(); Local<External> wrap = Local<External>::Cast(self->GetInternalField(0)); void* ptr = wrap->Value(); static_cast<Time*>(ptr)->hour = value->Int32Value(); } Handle<Value> get_min(Local<String> property, const AccessorInfo &info) { Local<Object> self = info.Holder(); Local<External> wrap = Local<External>::Cast(self->GetInternalField(0)); void* ptr = wrap->Value(); int value = static_cast<Time*>(ptr)->min; return Integer::New(value); } void set_min(Local<String> property, Local<Value> value, const AccessorInfo& info) { Local<Object> self = info.Holder(); Local<External> wrap = Local<External>::Cast(self->GetInternalField(0)); void* ptr = wrap->Value(); static_cast<Time*>(ptr)->min = value->Int32Value(); } int main(int argc, char* argv[]) { std::string js_str; read_file(std::cin, js_str); // Create a stack-allocated handle scope. HandleScope handle_scope; Handle<ObjectTemplate> global = ObjectTemplate::New(); // log()関数のコールバックを指定 global->Set(String::New("log"), FunctionTemplate::New(log_callback)); // Create a new context. //Persistent<Context> context = Context::New(); Persistent<Context> context = Context::New(NULL, global); // Enter the created context for compiling and // running the hello world script. Context::Scope context_scope(context); // オブジェクトの定義 Handle<ObjectTemplate> time_templ = ObjectTemplate::New(); time_templ->SetInternalFieldCount(1); time_templ->SetAccessor(String::New("hour"), get_hour, set_hour); // プロパティとアクセサ指定 time_templ->SetAccessor(String::New("min"), get_min, set_min); // オブジェクトに対応するC++のインスタンスを作成して登録 Time* p = new Time; p->hour = 12; p->min = 0; Local<Object> obj = time_templ->NewInstance(); obj->SetInternalField(0, External::New(p)); context->Global()->Set(String::New("LunchTime"), obj); // globalにLunchTimeオブジェクト登録 // Create a string containing the JavaScript source code. Handle<String> source = String::New(js_str.c_str()); // Compile the source code. Handle<Script> script = Script::Compile(source); // Run the script to get the result. Handle<Value> result = script->Run(); // Dispose the persistent context. context.Dispose(); // Convert the result to an ASCII string and print it. String::AsciiValue ascii(result); printf("%s\n", *ascii); return 0; }
以下のtest4.jsを読み込んで実行してみる。
test4.js
function dump_obj(obj) { for (var field in obj) { log(field + ":" + obj[field]); } } log(typeof LunchTime); dump_obj(LunchTime); // プロパティを列挙 LunchTime.hour = 11; // writeのテスト LunchTime.min = 10; dump_obj(LunchTime);
実行結果
# ./a.out < test4.js log: object <-- 型を確認 log: min:0 <-- プロパティが列挙できることを確認 log: hour:12 log: min:10 <-- プロパティの書き換えを確認 log: hour:11 undefined
for inでLunchTimeオブジェクトのプロパティが列挙できている。またプロパティの更新もできている。