Boost logo

Boost Users :

Subject: Re: [Boost-users] Copy of a C++ object extended with Boost.Python
From: 4ian (dark4ian_at_[hidden])
Date: 2009-08-28 10:20:30


I have found a discussion called "Getting Python Object from C++
object" : http://osdir.com/ml/python.c++/2003-08/msg00191.html
It use shared_ptr and boost "enable_shared_from_this" template. Thanks
to this, we could "just write object(p) to get the Python object
back." like described in the FAQ.

I have modified the code so as to implement a function which copy the
dict of an object "A" to the dict of another object "A" ( implementing
this as operator= would be better, but it's just to test ).
I've added the objects A to a container of type C so as to create a
shared_ptr and make sure that self() will return a valid shared_ptr.
However, it didn't seems to work, it crash when i try to do a "object
(self())" so as to get the python object :

----------------------
#include <assert.h>
#include <iostream>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/python.hpp>

using namespace boost;
using namespace boost::python;

struct RuntimeError
{
    RuntimeError( std::string msg ) : message( msg ) { }
    const char *what() const throw() { return message.c_str(); }
    std::string message;
};

void runtime_error( RuntimeError const &x )
{
    PyErr_SetString( PyExc_RuntimeError, x.what() );
}

class A : public enable_shared_from_this<A>
{
public:
    typedef shared_ptr<A> A_ptr;

    /* Here 'a' tries to get the shared_ptr representing the
    * python object from boost::python.
    * Certainly this only works after a shared pointer has
    * actually been created, e.g. by adding 'a' to a container
    * of type C. After that, shared_from_this() actually returns
    * a valid shared_ptr, which can be used for getting the
    * respective python::object.
    */
    virtual A_ptr self()
    {
        if ( _internal_weak_this.expired() )
            throw RuntimeError( "Shared pointer not available." );
        shared_ptr<A> self = shared_from_this();
        assert( self != 0 );
        return self;
    }

    //Very simple function to copy the dict of the python objects
    void Copy( A & o )
    {
        object(self()).attr("__dict__") = object(o.self()).attr
("__dict__");
    }

    virtual ~A() {};
};

class C
{
private:
    typedef A::A_ptr A_ptr;
public:
    void set( A_ptr a ) { this->a = a; } // store instance
    A_ptr get() { return this->a; }

private:
    A_ptr a;
};

BOOST_PYTHON_MODULE( self_test )
{
    register_exception_translator<RuntimeError>( &::runtime_error );

    class_<A>( "A" ).def( "self", &A::self );
    class_<C>( "C" ).def( "set", &C::set ).def( "get", &C::get );
}

int main()
{
    PyImport_AppendInittab( "self_test", &initself_test );
    Py_Initialize();

    A a_cpp;
    A a2_cpp;

    object main_module(( handle<>( borrowed( PyImport_AddModule
( "__main__" ) ) ) ) );
    object main_namespace = main_module.attr( "__dict__" );
    object self_test(( handle<>( PyImport_ImportModule
( "self_test" ) ) ) );
    main_namespace["self_test"] = self_test;
    main_namespace["a"] = &a_cpp;
    main_namespace["a2"] = &a2_cpp;

    try
    {
        handle<> ignored(( PyRun_String( "c = self_test.C();c.set
(a);a.self();print a;a.member=42;",
                                         Py_file_input,
                                         main_namespace.ptr(),
                                         main_namespace.ptr() ) ) );

        handle<> ignored(( PyRun_String( "c2 = self_test.C();c2.set
(a2);a2.self();print a2;a2.othermember=23;",
                                         Py_file_input,
                                         main_namespace.ptr(),
                                         main_namespace.ptr() ) ) );
    }
    catch ( error_already_set )
    {
        PyErr_Print();
    }

    a2_cpp.Copy(a_cpp); //Crash
}
----------------------

Theorically, the call to C::set would prevent the crash...

On 28 août, 00:19, OvermindDL1 <overmind..._at_[hidden]> wrote:
> On Thu, Aug 27, 2009 at 10:46 AM, 4ian<dark4..._at_[hidden]> wrote:
> > I'm afraid I'm unable to find this class or anything that can help me
> > to copy the Python __dict__ associated with my C++ object...
>
> > On 25 août, 21:55, OvermindDL1 <overmind..._at_[hidden]> wrote:
> >> On Tue, Aug 25, 2009 at 3:52 AM, 4ian<dark4..._at_[hidden]> wrote:
> >> > Thanks for you response !
> >> > When you say "that one wrapper helper", are you speaking about the
> >> > object class of Boost.python, or about a home made class ?
>
> >> Neither.  I do not recall the name of it, but you can subclass your
> >> class from it, then anytime your class has a python object containing
> >> it then you can use some getself comand or something like that, it is
> >> in the docs somewhere (but I am not in a good position to look at the
> >> docs right now, maybe tonight if you have not found it yet).
>
> Found it, it is in the FAQ, apparently the wrapper class I used was
> one I made, but it talks about how to make it there, and an
> alternate/better method if you are using shared_ptr:http://beta.boost.org/doc/libs/1_40_0/libs/python/doc/v2/faq.html#xref
> _______________________________________________
> Boost-users mailing list
> Boost-us..._at_[hidden]http://lists.boost.org/mailman/listinfo.cgi/boost-users


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net