Hi, all! After having bound hundreds of C-like functions i'm ready to bind my first class in v8. i've got it working so far except that my Weak Pointer callback isn't being triggered, and i have been unable to figure out why. i'm pasting the code here - it's a bit long, but i would really appreciate any insights on this, as i can't do ANY class- level wrapping until i figure out how to get the objects deleted properly.
Most of the code below was based on suggestions from: http://create.tpsitulsa.com/blog/2009/01/31/persistent-handles/ http://create.tpsitulsa.com/blog/2009/01/29/v8-objects/ It's worth noting that the v8 sample code doesn't have any examples of weak pointers :(. The class i'm wrapping, PathFinder, can be considered opaque for our purposes - the binding to the object appears to work, it's just that my dtor (pf_dtor()) is never called. The functions listed below are: - SetupPathFinderClass() sets up the class for JS-side access. Installs the ctor and class instance prototype - pf_ctor() - the instance constructor - pf_dtor() - the weak pointer callback - pf_wrap() - associates a PathFinder JS object with a C++ object and does the Persistent/Weak voodoo. i've tried with and without HandleScopes, but the results are the same - pf_dtor() is never being called. The C++ code (JS code follows): #include <v8/PathFinder.h> #include <v8.h> #include <v8/v8-convert.h> #include <v8/v8-plugin.h> #include <iostream> /* only for debuggering */ #ifndef CERR #define CERR std::cerr << __FILE__ << ":" << std::dec << __LINE__ << " : " #endif namespace v8 { namespace p3 { using namespace ::v8::bind; using namespace ::v8::convert; //static const void * pf_bind_cx() { static const int x=7;return &x;} static void pf_dtor(Persistent< Value > object, void *parameter) { CERR << "pf_dtor() PathFinder @"<<parameter<<'\n'; PathFinder * pf = static_cast<PathFinder*>( parameter ); //UnbindNative( pf_bind_cx(), parameter, pf ); if( pf != &::v8::p3::plugin::PluginPath() ) { delete pf; } object.Dispose(); object.Clear(); } static Persistent<Object> pf_wrap( Handle<Object> _self, PathFinder * value ) { //HandleScope scope; //BindNative( pf_bind_cx(), value, value ); Persistent<Object> self( Persistent<Object>::New(_self) ); self.MakeWeak( value, pf_dtor ); self->SetInternalField(0,External::New(value)); self->Set(String::New("bogo"),String::New("bogo was here")); CERR << "Wrapped PathFinder @"<<value<<" in a Persistent<Object>.\n"; //return scope.Close(self); return self; } static Handle<Value> pf_ctor(const Arguments& argv) { if (!argv.IsConstructCall()) return ThrowException(String::New("Cannot call constructor as function")); const int argc = argv.Length(); if( (1 == argc) && argv[0]->IsExternal() ) { External * ex = External::Cast( *argv[0] ); if( ex ) { return pf_wrap( argv.This(), static_cast<PathFinder*>(ex->Value ()) ); } else { return ThrowException(String::New("First argument to ctor failed External::Cast()")); } } //HandleScope hscope; std::string a0 = (argc>0) ? JSToStdString(argv[0]) : ""; std::string a1 = (argc>1) ? JSToStdString(argv[1]) : ""; std::string a2 = (argc>2) ? JSToStdString(argv[2]) : ""; CERR << "PathFinder(["<<a0<<"], ["<<a1<<"], ["<<a2<<"])\n"; PathFinder * pf = new PathFinder( a0, a1, a2 ); //return hscope.Close( pf_wrap( argv.This(), pf ) ); return pf_wrap( argv.This(), pf ); //return hscope.Close( pf_wrap( argv.This(), pf ) ); } Handle<Value> SetupPathFinderClass(const Handle<Object> target ) { // Set up prototype: Handle<FunctionTemplate> ctor = FunctionTemplate::New(pf_ctor); Local<ObjectTemplate> objt = ctor->InstanceTemplate(); objt->SetInternalFieldCount(1); // Install ctor: Handle<Function> pffunc( ctor->GetFunction() ); target->Set(String::New("PathFinder"), pffunc ); // Install instance wrapping PluginPath() shared object: Handle<Value> pfex( External::New( &::v8::p3::plugin::PluginPath () ) ); Handle<Object> pfobj = pffunc->NewInstance( 1, &pfex ); pffunc->Set(String::New("plugins"), pfobj ); return pfobj; } }} // namespaces i've created hundreds of PathFinder objects in small scopes to try to force GC, but my debugging message in pf_dtor() never gets output: var my = {p:null}; { for( var i = 0; i < 5; ++i ) { var p = ['/usr/bin','/bin','~/bin']; my.p = new PathFinder(p.join(''+i),"",""+i); //delete my.p; } print('my.p=',my.p,typeof my.p,my.p.bogo); delete my.p; print('my.p=',my.p); } print('my.p=',my.p); print ('PathFinder.plugins=',PathFinder.plugins,PathFinder.plugins.bogo); print("Bye!"); The output is: step...@jareth:~/cvs/fossil/v8-addons/addons$ m && ./shell js/pf.js make: Nothing to be done for `default'. PathFinder-js.cc:43 : Wrapped PathFinder @0xb7c940a0 in a Persistent<Object>. PathFinder-js.cc:69 : PathFinder([/usr/bin0/bin0~/bin], [], [0]) PathFinder-js.cc:43 : Wrapped PathFinder @0x88cda78 in a Persistent<Object>. PathFinder-js.cc:69 : PathFinder([/usr/bin1/bin1~/bin], [], [1]) PathFinder-js.cc:43 : Wrapped PathFinder @0x88cda40 in a Persistent<Object>. PathFinder-js.cc:69 : PathFinder([/usr/bin2/bin2~/bin], [], [2]) PathFinder-js.cc:43 : Wrapped PathFinder @0x88cdc10 in a Persistent<Object>. PathFinder-js.cc:69 : PathFinder([/usr/bin3/bin3~/bin], [], [3]) PathFinder-js.cc:43 : Wrapped PathFinder @0x88cdd00 in a Persistent<Object>. PathFinder-js.cc:69 : PathFinder([/usr/bin4/bin4~/bin], [], [4]) PathFinder-js.cc:43 : Wrapped PathFinder @0x88cddf0 in a Persistent<Object>. my.p= [object Object] object bogo was here my.p= undefined my.p= undefined PathFinder.plugins= [object Object] bogo was here Bye! --------------------------------------- (end demo) :-? --~--~---------~--~----~------------~-------~--~----~ v8-users mailing list [email protected] http://groups.google.com/group/v8-users -~----------~----~----~----~------~----~------~--~---
