Tomasu / LuaGlue

C++11 Lua 5.2 Binding Library
zlib License
79 stars 22 forks source link

(shared) pointers support #8

Closed JMLX42 closed 10 years ago

JMLX42 commented 10 years ago

Hello,

for obvious memory management reasons, my API makes it impossible to create anything else but shared pointers (std::shared_ptr).

My classes are all defined like this:

class Foo
{
  public:
    typedef std::shared_ptr Ptr;

    Ptr create() { return std::shared_ptr(new Foo()); }

  private:
    Foo();
};

How can I use LuaBind to map not just the Foo class but Foo::Ptr?

state
  .Class("Foo")
  end()
  .Class("FooPtr")
  .end()

How can I properly bind Foo::Ptr using LuaGlue? How do I map methods past this point? Since all my methods are declared as Foo members, but always called with the -> operator (since I manipulate only Foo::Ptr shared pointers).

Maybe LuaGlue's Class method should have overrides to handle class derived from std::shared_ptr using std::enable_if and std::convertible_to/std::base_of to make this behavior automatic. How can I help?

Finally, when I pass a Foo::Ptr object to Lua, how will the internal std::shared_ptr reference counter behave? I expect the shared pointer to be copied before entering the Lua function scope and destroyed when the function ends. Is that correct? If it is, will reference counting still work when I use the object inside my Lua code?

Thank you for all the great work!

JMLX42 commented 10 years ago

Something I forgot to add is that my C++ methods also return only std::shared_ptr:

class Foo
{
  public:
    typedef std::shared_ptr Ptr;
    Ptr create() { return std::shared_ptr(new Foo()); }
    std::shared_ptr bar() { return _bar; }
  private:
    Foo();
    std::shared_ptr _bar;
};

How does that work in LuaGlue?

I'm guessing that LuaGlue only passes pointers to Lua. At least that's what I see from your invoke.cpp example. As a std::shared_ptr can always be used as a pointer, I'm guessing it "should" work quite easily. I just want your advice on this, especially on the reference counter thing.

Tomasu commented 10 years ago

I'll have to try it out to know for sure. It "should" work, as shared_ptrs are just templates, and luaglue works fine with template classes.

It also works with statically allocated objects, but that currently leads to a leak in the core code, so I'd avoid that for now till I figure that one out properly.

JMLX42 commented 10 years ago

The main issue is the fact that I will use LuaGlue to declare some classes but that all my interface acutally return/use std::shared_ptr of those classes.

So when I try to use the classes bound with LuaGlue, the only thing I get are "userdata"...

Tomasu commented 10 years ago

You should probably register them wrapped in std::shared_ptr's (best to use pointers to shared_ptrs atm, theres a memory leak in static allocated argument passing). That may fix it.

JMLX42 commented 10 years ago

That's what I tried. But then the method() method won't work anymore since my member method references are in class C, not in std::shared_ptr. I'll try to override method() to see if I can deal with that... Anyway, with the const thing fixed we're really really close to something that works :+1:

Tomasu commented 10 years ago

Ah. Yeah, that's an issue. Might need direct internal support for a shared_ptr/smart_ptr mode. This needs some thought.

JMLX42 commented 10 years ago

There is also a problem with return types being std::shared_ptr and not C: it makes method call return values unsuable in Lua. We need some way to make sure that when we bind a class, we also bind it's ptr/std::shared_ptr type.

But Lua does not have a dereferencing operator, right? It requires some thinking indeed...

Tomasu commented 10 years ago

I think having a special memory managed mode that deals with the shared_ptr stuff internally would be needed. it'd bind to lua with the raw type, but C++ with the shared_ptr. And I think the only way that's possible is if the api supports that through say a SharedClass api? It'd mean more template magic.

JMLX42 commented 10 years ago

Shared pointer need some special love since we probably want to use the reference counter properly. Currently I can use my std::shared_ptr by doing this:

class.invokeVoidMethod("myMethod", &_scriptClassStub, target.get());

where target is an std::shared_ptr. It works and when I try to use it in my Lua code there is no error. The only problem I have is that all the methods I bound using LuaGlue.Class() return std::shared_ptrs. I have bound the template class of those shared_ptr... but not the templated shared_ptr class itself.

Tomasu commented 10 years ago

The lua side probably needs to notice shared_ptrs and unwrap them. maybe do the "release" side of the "get" call when the _gc metamethod is called.

JMLX42 commented 10 years ago

If there's a _gc metamethod then the ref. counting should be doable. Can we also override de ":" operator in order to mimic what the "->" operator does for shared_ptr?

Tomasu commented 10 years ago

I've just added initial support for std::shared_ptrs. It handles properly passing around shared_ptrs as arguments and return values. I think it may work for the majority of your use cases. I'm working on fixing the memory leaks that occur with the static objects and the new shared_ptr code... Might take the rest of the day to figure this one out. but see if you can't get it working.