JavascriptのオブジェクトとC++のオブジェクトをつなげてみる。
まともに使うとなるとやることはたくさんあるが、
最低限必要なものはわかった。
SetInternalFieldでJavascriptからは見えない、C++ポインタを設定するのがみそ。
main内で明示的に初期化と終了をしているのは、
main前後に持ってくると不都合な場合があるから。
listが自動開放になっているのは手抜きです。
メモリリークチェックしてないや。
コメントがないのは、わざとです。
using namespace v8;
class TestX : public smart_ptr::ref_counted<TestX>
{
public:
TestX()
{
}
~TestX()
{
}
static bool initialize();
static void terminate();
static Handle<ObjectTemplate> make();
static Handle<Value> GetPointX(
Local<String> property,
const AccessorInfo &info);
static void SetPointX(
Local<String> property,
Local<Value> value,
const AccessorInfo& info);
static Handle<Value> constructor(const Arguments& args);
int x_;
static Persistent<ObjectTemplate> template_;
typedef std::list<smart_ptr::intrusive_ptr<TestX> > InstanceList;
static InstanceList instanceList_;
};
Persistent<ObjectTemplate> TestX::template_;
TestX::InstanceList TestX::instanceList_;
bool TestX::initialize()
{
if(template_.IsEmpty()){
HandleScope handle_scope;
Handle<ObjectTemplate> templ= ObjectTemplate::New();
templ->SetInternalFieldCount(1);
templ->SetAccessor(String::NewSymbol("x"), GetPointX, SetPointX);
template_ = Persistent<ObjectTemplate>::New( handle_scope.Close(templ) );
}
return true;
}
void TestX::terminate()
{
template_.Dispose();
}
Handle<Value> TestX::GetPointX(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<TestX*>(ptr)->x_;
return Integer::New(value);
}
void TestX::SetPointX(Local<String> property, Local<Value> value,
const AccessorInfo& info)
{
Local<Object> self = info.Holder();
int i = self->InternalFieldCount();
Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
void* ptr = wrap->Value();
static_cast<TestX*>(ptr)->x_ = value->Int32Value();
}
Handle<Value> TestX::constructor(const Arguments& args)
{
if(!args.IsConstructCall()){
return v8::Undefined();
}
Handle<ObjectTemplate> temp = template_;
Local<Object> obj = temp->NewInstance();
smart_ptr::intrusive_ptr<TestX> p( new TestX );
instanceList_.push_back(p);
obj->SetInternalField(0, External::New(p.get()));
return obj;
}
Handle<Value> Print(const Arguments& args)
{
if (args.Length() < 1) return v8::Undefined();
HandleScope scope;
Handle<Value> arg = args[0];
String::Utf8Value value(arg);
std::cout << "print: " << *value << std::endl;
return v8::Undefined();
}
int main(int argc, char** argv)
{
HandleScope handle_scope;
TestX::initialize();
Handle<ObjectTemplate> global = ObjectTemplate::New();
global->Set(String::New("print"), FunctionTemplate::New(Print));
global->Set(String::New("TestX"), FunctionTemplate::New(TestX::constructor));
Persistent<Context> context = Context::New(NULL, global);
Context::Scope context_scope(context);
Handle<String> source = String::New("print(\’Hello\’);var p = new TestX();p.x = 1;var p2 = new TestX(); p2.x = 2;");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();
TestX::terminate();
context.Dispose();
String::AsciiValue ascii(result);
std::cout << *ascii << std::endl;
return 0;
}
0 件のコメント:
コメントを投稿