|
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