On 1/15/2013 2:47 PM, Ross Bencina wrote:|
> On 16/01/2013 8:23 AM, Tim Mensch wrote:
>> The "weaktable" keeps a weak reference to the existing Lua
>> USERDATA, so when I "push" an object from C++ and there is an
>> existing Lua object, it can push a reference to it rather than
>> creating a new Lua USERDATA (I find that, in games especially, you
>> end up with a LOT of extra garbage collection if you have to
>> create a new USERDATA every time you want C++ to push the object).
>> While the main object USERDATA exists, maintable holds a strong
>> C++ reference (shared_ptr) to the object, so it won't be deleted on
>> the C++ side. When the USERDATA ends up being garbage collected,
>> the shared_ptr<> is deleted, releasing the C++ reference.
> One question: Am I correct to assume that this requires that all C++
> classes that can be referenced from Lua have their lifetimes managed
> using shared_ptr in the C++ code as well?
No, it actually doesn't require that. In the Dub configuration, I set SOME objects to use this lifetime management, and I set others to be handled differently.
Some simple POD times ("Point" or "Rect" types being obvious examples) get allocated into a USERDATA directly, for instance. Not just a "pointer to a Vector", but the full Vector is copied into the USERDATA. Or it CAN be; it can also reference a Vector that's part of another object.
And, in response to a comment about this elsewhere in this discussion, yes, it DOES keep a reference to the parent object if you do that.
> That kind of precludes binding an existing code base that does not
> (and/or can not) use shared_ptr doesn't it?
Dub, and by extension my version of Dub, works fine with existing code. It was designed to wrap lots of different existing code bases.
When I'm not using a class that derives from "ScriptLink" type, I just can't add additional fields to those objects (a Vector2d will forever only have x and y members, for instance) -- or at least you can't do that in a way that allows C++ to push that object safely onto the stack. Something like a 2d vector wouldn't likely need additional members, while it's very useful for a full game object to get additional arbitrary traits.
You can always wrap an object in a proxy to bind additional members to it. For an object that lives in Lua until it dies, that's perfectly fine. It's only if the object needs to also be managed by C/C++ and pushed onto the stack from a C function that you end up with problems, because C/C++ will create a new instance of the object without the proxy wrapping it with your additional members/attributes.
It's that kind of object passing (back and forth seamlessly between C++ and Lua) that I'm trying to support with my ScriptLink. In my game engine architecture, the objects are primarily managed by (and rendered by) C++, and sometimes (collisions being a prime example) I need to pass in to Lua the fact that something is happening with one of its objects, and I need to push it on the stack.