Search code examples
c++lualuabind

Return class pointer to lua with luabind


Is there any way that I can, in a C++ function, return a pointer to a class to lua? I have tried this, among other more desperate things:

P* GetP()
{
    return g_P;
}

module(L)
[
    def("GetP", &GetP)
]

This makes the program crash even before running the first line in main(), even if the code just sits in a function that is never called.

I thought it was a problem that P was unknown to luabind, but even telling it what it was failed.

module(L)
[
    class_<P>("ClassP")
    .def(constructor<>())
]

This could be because P have a somewhat complex inheritance hierarchy, not sure.

class GO;
class L;
class C : public GO;
class P : public C, L;

I have tried different approaches to tell luabind of the inheritance of P, none gave any result.

The crash I get is a Unhandled exception at 0x0059a064 in program.exe: 0xC0000005: Access violation reading location 0x00000004, found in xtree.

_Pairib insert(const value_type& _Val)
    {   // try to insert node with value _Val
        _Nodeptr _Trynode = _Root();
        _Nodeptr _Wherenode = _Myhead;
        bool _Addleft = true;   // add to left of head if tree empty

Any help appreciated.


Solution

  • Why do you want the class pointer in the lua code? As a C++ class, it's going to be opaque... or better be. ~smile~

    Perhaps set up a std::map in the C++ code and store the pointer in the map with a hash value and pass the hash value to the lua? The lua can then use that to pass back to the C++ code elsewhere.

    EDIT: You could dereference P a bit and pass around a hash as a substitute for the this in P.

    Keep in mind that thing:Method() is just a shorthand for thing.Method( thing ) -- so, using a hash for thing is still largely the same construct, but a little less OO in appearance to the eye.

    Something similar to this would work...

    std::map<unsigned,P*> p_Map;
    
    void p_AddValue( unsigned hash, int aValue )
    {
        if( p_Map.find( hash ) != p_Map.end() )
            p_Map[hash]->AddValue( aValue );
    }
    
    unsigned p_New()
    {
        P* p = new P();
        unsigned hash;
    
        do hash = GenerateHash( p );
        while( p_Map.find( hash ) != p_Map.end() );
    
        p_Map[hash] = p;
    
        return hash;
    }
    
    module(L)
    [
        def("p_AddValue", &p_AddValue)
        def("p_New", &p_New)
    ]
    

    Then in Lua you should be able to do things like this...

    local p1 = p_New();
    local p2 = p_New();
    
    p_AddValue( p1, 5 );
    p_AddValue( p2, 10 );
    

    etc.

    It's not a perfect solution, but it should get you around the issue you're having. Hopefully someone else maybe can come along with a better answer?

    RE-EDIT: come to think of it, though a tad cumbersome, there might be another way that would allow you to use the P class (indirectly) via a proxy class in Lua...

    class PProxy
    {
        protected:
    
           P  p;
    
        public:
    
           PProxy() : P() {};
           ~PProxy() {};
    
           void AddValue( int aValue ) { p.AddValue( aValue ); }
    }
    
    module(L)
    [
        class_<PProxy>("P")
        .def(constructor<>())
        .def("AddValue", &PProxy::AddValue)
    ]