Thanks, Matthias! It all seems to work now, and it clears up a few
things.

-Dave

On Apr 22, 7:02 am, Matthias Ernst <[email protected]> wrote:
> On Thu, Apr 21, 2011 at 10:57 PM, Dave <[email protected]> wrote:
> > I *think* understand your suggestion for keeping the parent/child
> > cluster alive via an internal field, but let me make sure that I got
> > it right:
>
> > Should I add a *second* internal field to the vector objects that
> > points to info.This()?
>
> Yes, that's my suggestion.
>
> > When the parent (Sprite) callback is invoked,
> > does it need to check if there's something in the second field, and if
> > so, just skip deletion?
>
> No. You don't need to check anything. The magic is that the link from
> child-wrapper to parent-wrapper is followed by the GC and
> thus guarantees that the callback for the parent will not be invoked at all
> as long as someone even only references the child. There is no need for a
> child callback at all, everything gets managed through the parent.
>
> Small chart attached explains it all ;-)
>
> Matthias
>
> I'm guessing that the Vector callback would
>
>
>
>
>
>
>
> > then have to clear out its parents field so the parent could then
> > delete properly when its callback is invoked again.
>
> > eg:
>
> > void DestroySprite( Persistent<Value> obj,
> >                    void* param )
> > {
> >    // If this field is populated, then bail since we have an attached
> > child.
> >    if (obj->GetPointerFromInternalField(1))
> >    {
> >        return;
> >    }
>
> >    CSprite* s = static_cast<CSprite*>(param);
> >    assert(s);
>
> >    delete s;
>
> >    obj.Dispose();
> >    obj.Clear();
> > }
>
> > On Apr 19, 1:57 am, Matthias Ernst <[email protected]> wrote:
> > > On Tue, Apr 19, 2011 at 12:31 AM, Dave <[email protected]> wrote:
> > > > Hi all,
>
> > > > I'm experimenting with V8 for scripting in a game engine. However, I'm
> > > > having trouble returning member objects of C++ classes by reference.
> > > > For example, let's say I have the following C++ classes (trimmed for
> > > > simplicity):
>
> > > > class Vector
> > > > {
> > > > public:
> > > >  int X;
> > > >  int Y;
> > > > };
>
> > > > class Sprite
> > > > {
> > > > public:
> > > >  Vector Position;
> > > > };
>
> > > > After wrapping these, I add a few Sprite objects to the global object
> > > > (eg: Sprite_1, Sprite_2, etc.). In Javascript, I'd like to manipulate
> > > > their positions, like so:
>
> > > > Sprite_1.Position.X = 32;
>
> > > > However, this doesn't work (ie: the sprite's position remains the
> > > > same), but this does:
>
> > > > Sprite_1.Position = new Vector(32,0); // Sprite position is correctly
> > > > updated
>
> > > > The reason the former doesn't work is because my 'GetPosition'
> > > > accessor for the Sprite class will create a *new* Vector object and
> > > > return that. In other words, the accessor will create a new (weak)
> > > > persistent handle and wrap it around the external data. This
> > > > essentially returns the vector as a value instead of a reference. I'd
> > > > like to return it as a reference, since that would be the expected
> > > > behavior. However, I'm not sure how I would go about doing that.
>
> > > > My code looks something like this:
>
> > > "Something like" is always difficult since I don't know what other
> > details
> > > to point out.
>
> > > > Handle<Value> GetPosition( Handle<String>, const AccessorInfo& info )
> > > > {
> > > >  Local<Object> obj = info.This();
> > > >  Local<External> wrap = Local<External>::Cast( obj-
> > > > >GetInternalField(0) );
>
> > > "Set/GetPointerIn/FromInternalField" is simpler and might even be faster
> > > than using External.
>
> > > >  Vector pos = static_cast<Sprite*>( wrap->Value() )->Position();
> > > >  Vector* v = new Vector(pos);
>
> > > >  HandleScope handle_scope;
> > > >  Handle<Object> instance = VectorTemplate->InstanceTemplate()-
> > > > >NewInstance(); // VectorTemplate is defined elsewhere
> > > >  Persistent<External> weak =
> > > > Persistent<External>::New( External::New(v) );
>
> > > I don't think this is what you want. You have now a weak reference from
> > the
> > > vector wrapper to the native vector. V8 GC may now any time collect the
> > > native vector (no one else is referring to it) and leave your wrapper
> > with
> > > nothing. You want to create a weak reference to the wrapper object
> > > "instance".
>
> > > >  weak.MakeWeak( v, Vector_Dispose );
> > > >  instance->SetInternalField(0,weak);
>
> > > >  return handle_scope.Close(instance);
> > > > }
>
> > > > I was thinking that instead of creating a new Vector, I could just
> > > > wrap a local handle around the Sprite's Position member.
>
> > > This would be the right thing to do, wrapping &(sprite->Position).
>
> > > I'm guessing
>
> > > > that a persistent handle shouldn't be necessary since the lifetime of
> > > > the member object is coupled with the parent Sprite.
>
> > > Yes and no. The member also only lives as long as the parent. The JS
> > client
> > > might acquire a reference to the child and then drop the reference to the
> > > parent - which would allow the parent _and_ the child to be deleted on
> > the
> > > native side. Probably not what you want to happen. You need to make a
> > > reference to the child keep the whole "cluster" alive. You'd do that by
> > > introducing a reference from the child wrapper to the parent wrapper,
> > e.g.
> > > by adding an internal field to the child object in GetPosition that
> > points
> > > to info.This().
>
> > > Matthias
>
> > > > Does anyone have any thoughts on this? I'm still getting used to V8's
> > > > concepts...
>
> > > > Thanks,
> > > > Dave
>
> > > > --
> > > > v8-users mailing list
> > > > [email protected]
> > > >http://groups.google.com/group/v8-users
>
> > --
> > v8-users mailing list
> > [email protected]
> >http://groups.google.com/group/v8-users
>
>  heap.png
> 44KViewDownload

-- 
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users

Reply via email to