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()? 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? 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