V8 JavaScriptエンジン - 変数の追加
V8 JavaScriptエンジンの組み込み - 変数の追加
V8 JavaScriptエンジンの組み込みの続き。今度はグローバル領域への変数の追加をしてみる。追加する変数は以下のとおり。
変数名:LogCalledCount
内容:log()を呼び出した回数がカウントされる。
Read/Writeともに可。
変数を追加する場合は、変数名とそれに対応するアクセサ(setter,getter)をオブジェクトテンプレートに登録する。
#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 int log_called_count = 0;
// 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;
log_called_count++;
return v8::Undefined();
}
// LogCalledCount変数のアクセサ
Handle<Value> get_log_called_count(Local<String> property,
const AccessorInfo& info) {
return Integer::New(log_called_count);
}
void set_log_called_count(Local<String> property, Local<Value> value,
const AccessorInfo& info) {
log_called_count = 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));
// LogCalledCount変数のアクセサを指定
global->SetAccessor(String::New("LogCalledCount"),
get_log_called_count, set_log_called_count);
// 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);
// 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;
}
上記のソースでは、変数名"LogCalledCount"に対し、アクセサget/set_log_called_count()を登録している。JavaScriptからLogCalledCount変数にアクセスすると、アクセサ関数が呼び出される。アクセサ関数では、log()の呼び出し回数をカウントしているlog_called_count変数をRead/Writeしている。
以下のtest3.jsを読み込んで実行してみる。
test3.js
log("LogCalledCount:" + LogCalledCount);
log("LogCalledCount:" + LogCalledCount);
LogCalledCount = 0; // reset
log("LogCalledCount:" + LogCalledCount);
実行結果
# ./a.out < test3.js log: LogCalledCount:0 log: LogCalledCount:1 <-- log()が呼ばれたのでインクリメントされている。 log: LogCalledCount:0 <-- 0を書き込んだので、カウンタが戻っている。 undefined
log()の呼び出し回数がカウントされ、Read/Writeできていることが確認できる。
次にグローバル空間にオブジェクトを追加してみる。
つづく。
