After some more digging I think I've got it. Using Persistent::MakeWeak you
can set a callback for the objects destruction. Everything seems to be
working ok now, so I'll attach my code for future users to find. If you see
anything wrong with it please speak up.
Jake
--~--~---------~--~----~------------~-------~--~----~
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
-~----------~----~----~----~------~----~------~--~---
#include <v8/v8.h>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace v8;
class Point {
public:
Point(int px = 0, int py = 0) : x(px), y(py) {}
int x, y;
};
Handle<Value> Point_GetX(Local<String> property, const AccessorInfo& info);
void Point_SetX(Local<String> property, Local<Value> value, const AccessorInfo& info);
Handle<Value> Point_GetY(Local<String> property, const AccessorInfo& info);
void Point_SetY(Local<String> property, Local<Value> value, const AccessorInfo& info);
Handle<Value> Point_Create(const Arguments& args);
void Point_Destroy(Persistent<Object> self, void* parameter);
Handle<String> ReadFile(const char* filename);
Handle<Value> Print(const Arguments& args);
int main()
{
HandleScope handleScope;
Handle<FunctionTemplate> pointFunctionTemplate = FunctionTemplate::New(Point_Create);
pointFunctionTemplate->SetClassName(String::New("Point"));
Handle<ObjectTemplate> pointInstanceTemplate = pointFunctionTemplate->InstanceTemplate();
pointInstanceTemplate->SetInternalFieldCount(1);
pointInstanceTemplate->SetAccessor(String::New("x"), Point_GetX, Point_SetX);
pointInstanceTemplate->SetAccessor(String::New("y"), Point_GetY, Point_SetY);
Handle<ObjectTemplate> globals = ObjectTemplate::New();
globals->Set(String::New("print"), FunctionTemplate::New(Print));
globals->Set(String::New("Point"), pointFunctionTemplate);
Persistent<Context> context = Context::New(0, globals);
Context::Scope contextScope(context);
Handle<String> source = ReadFile("test.js");
Handle<Script> script = Script::Compile(source);
Handle<Value> result = script->Run();
context.Dispose();
return 0;
}
Handle<Value> Point_GetX(Local<String> property, const AccessorInfo& info)
{
Local<Object> self = info.Holder();
Local<External> external = Local<External>::Cast(self->GetInternalField(0));
Point* p = static_cast<Point*>(external->Value());
return Integer::New(p->x);
}
Handle<Value> Point_GetY(Local<String> property, const AccessorInfo& info)
{
Local<Object> self = info.Holder();
Local<External> external = Local<External>::Cast(self->GetInternalField(0));
Point* p = static_cast<Point*>(external->Value());
return Integer::New(p->y);
}
void Point_SetX(Local<String> property, Local<Value> value, const AccessorInfo& info)
{
Local<Object> self = info.Holder();
Local<External> external = Local<External>::Cast(self->GetInternalField(0));
Point* p = static_cast<Point*>(external->Value());
p->x = value->Int32Value();
}
void Point_SetY(Local<String> property, Local<Value> value, const AccessorInfo& info)
{
Local<Object> self = info.Holder();
Local<External> external = Local<External>::Cast(self->GetInternalField(0));
Point* p = static_cast<Point*>(external->Value());
p->y = value->Int32Value();
}
Handle<Value> Point_Create(const Arguments& args)
{
HandleScope handleScope;
if (!args.IsConstructCall())
return ThrowException(String::New("Cannot call constructor as function"));
if (args.Length() != 2)
return ThrowException(String::New("Expected two integer arguments"));
Point* p = new Point();
p->x = args[0]->Int32Value();
p->y = args[1]->Int32Value();
// make a persistant handle for the instance and
// make it weak so we get a callback on destruction
Persistent<Object> self = Persistent<Object>::New(args.Holder());
self.MakeWeak(0, Point_Destroy);
self->SetInternalField(0, External::New(p));
return self;
}
void Point_Destroy(Persistent<Object> self, void* parameter)
{
Local<External> external = Local<External>::Cast(self->GetInternalField(0));
delete static_cast<Point*>(external->Value());
}
Handle<String> ReadFile(const char* filename)
{
std::ifstream fin(filename);
if (!fin) {
return Handle<String>();
}
std::ostringstream os;
os << fin.rdbuf();
return String::New(os.str().c_str());
}
Handle<Value> Print(const Arguments& args)
{
bool first = true;
for (int i = 0; i < args.Length(); ++i) {
HandleScope handleScope;
if (first)
first = false;
else
std::cout << ' ';
std::cout << *String::AsciiValue(args[i]);
}
std::cout << std::endl;
return Undefined();
}