Shared pointers and wrapper base.

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

Shared pointers and wrapper base.

Nigel Atkinson-2
I had some problems with code hitting an assert, when calling a method,
that has been set up to be over-ridden.  The objects are being held by
shared pointers which in turn where in a list.  Basically when an object
is created by a script, then a shared pointer is given to C++ land to
hold on to, and then the Lua side of things lets go of the object, bad
things happen.

I've noticed the weak ref held by wrap_base gets clobbered as soon as
you do "obj = nil", even BEFORE it is garbage collected!

Attached is a small program that demonstrates the problem, and a small
patch the fixes it (if you un-comment the code in the example too).

There are various other (better?) ways this could be fixed, my patch is
basically the path of least resistance. Other ways could be:

- Instead of assert, throw an exception.
- Provide an "isValid" function.
- A "callp" or something that is just like "call", except returns an
error code if the weak reference held by wrap_base shows up nil.

Different situations call for different behaviour when this happens.  Do
you ignore it and carry on (perhaps it's destined for deletion next
render frame)?  Do you just call the default method instead?

What does everyone think?  Anyone else 'find' this? :-)

Nigel Atkinson

#include <luabind/luabind.hpp>
#include <lua.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>

using namespace std;
using namespace luabind;

class test
        test() { cout << "Hello" << endl; }
        virtual ~test() { cout << "Goodbye" << endl; }
        virtual void method() { cout << "Method!" << endl; }

class test_wrapper : public test, public luabind::wrap_base

        virtual void method()
                        //lua_State* L = m_self.state();
            //if( ! lua_isnil( L, -1 ) )
                call<void>( "method" );
            lua_pop( L, 1 );

        static void default_method( test *ptr )

typedef boost::shared_ptr<test_wrapper> test_ptr;

test_ptr stored_ptr;

void store( test_ptr ptr )
    stored_ptr = ptr;

int main()
    lua_State *L = lua_open();

    luaL_openlibs( L );


        class_<test, test_wrapper, test_ptr>("tester")
        .def("method", &test::method, &test_wrapper::default_method ),
        def( "store", &store )

    const char* str =
        "print 'Whooppie!'\n"
        "t = tester()\n"
        "t = nil\n";

    if( luaL_dostring(L, str ) )
        cout << "Error! " << lua_tostring(L,-1) << endl;


    lua_gc(L, LUA_GCCOLLECT, 0 );


    stored_ptr.reset(); // un-store before closing lua state.


>From 277222d1a9d49d155c058bd507b43569f6ac9af9 Mon Sep 17 00:00:00 2001
From: Nigel Atkinson <[hidden email]>
Date: Tue, 11 Jan 2011 21:35:08 +1100
Subject: [PATCH] Small change to allow wrapper code to test for possible assert case.

 luabind/wrapper_base.hpp |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/luabind/wrapper_base.hpp b/luabind/wrapper_base.hpp
index d54c668..9b64f5b 100755
--- a/luabind/wrapper_base.hpp
+++ b/luabind/wrapper_base.hpp
@@ -63,7 +63,7 @@ namespace luabind
     #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, <luabind/wrapper_base.hpp>, 1))
  #include BOOST_PP_ITERATE()
- private:
+ protected:
  wrapped_self_t m_self;

Gaining the trust of online customers is vital for the success of any company
that requires sensitive data to be transmitted over the Web.   Learn how to
best implement a security strategy that keeps consumers' information secure
and instills the confidence they need to proceed with transactions. 
luabind-user mailing list
[hidden email]