-------------------------------------------------
BOOST_PYTHON_MODULE(MyModule)
{
class_<MyObject>("MyObject")...
}
-------------------------------------------------
I call then python, making an instance of MyObject accessible :
-------------------------------------------------
MyObject anInstance;
object main_module((handle<>( borrowed( PyImport_AddModule
( "__main__" ) ) ) ) );
object main_namespace = main_module.attr( "__dict__" );
object myModule( (handle<>(PyImport_ImportModule("MyModule"))) );
main_namespace["anInstance"] = ptr(&anInstance);
try
{
handle<> ignored(( PyRun_String( "anInstance.aNewMember = 1;print
anInstance.aNewMember;",
Py_file_input,
main_namespace.ptr(),
main_namespace.ptr() ) ) );
}
catch ( error_already_set )
{
PyErr_Print();
}
-------------------------------------------------
You can observe that I've added a member ( aNewMember ) to MyObject
instance.
But if I make a copy of my object :
-------------------------------------------------
MyObject anotherInstance = anInstance;
main_namespace["anotherInstance"] = ptr(&anotherInstance);
try
{
handle<> ignored(( PyRun_String( "print
anotherInstance.aNewMember;",
Py_file_input,
main_namespace.ptr(),
main_namespace.ptr() ) ) );
}
catch ( error_already_set )
{
PyErr_Print();
}
-------------------------------------------------
I have a error saying that MyObject hasn't any "aNewMember" member.
What I have added with python has not been copied/transfered.
Is there a workaround to add permanently some new members to wrapped
objects ?
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users
You are adding an entry to the __dict__ of the wrapper class that
contains the MyObject, but on the line MyObject anotherInstance =
anInstance; you are creating a copy of only the C++ object, not the
wrapper object that has the __dict__. You need to make a copy of it
through the Python bindings, not directly on the C++ copy-constructor
because then you are just copying the MyObject, not the wrapper
object.
I have worked around it by putting a dict in MyObject and exposing it
to python as __dict__ though, just make sure you overload your copy
constructor so you copy the dict too and not just make a copy of the
dict handle, that is important. I did this work-around in an odd way,
not sure it would work directly in Boost.Python, but I would think so.
I think the proper way in Boost.Python would be to (multi-)subclass
your MyObject from that one wrapper helper so you can get the python
self from your class's this, then you can copy the self (not the
handle, again this is important) to the new one as well.
On 24 août, 22:01, OvermindDL1 <overmind...@gmail.com> wrote:
> Boost-us...@lists.boost.orghttp://lists.boost.org/mailman/listinfo.cgi/boost-users
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).
On 25 août, 21:55, OvermindDL1 <overmind...@gmail.com> wrote:
> On Tue, Aug 25, 2009 at 3:52 AM, 4ian<dark4...@gmail.com> 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).
> _______________________________________________
> Boost-users mailing list
> Boost-us...@lists.boost.orghttp://lists.boost.org/mailman/listinfo.cgi/boost-users
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
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...@gmail.com> wrote:
> Boost-us...@lists.boost.orghttp://lists.boost.org/mailman/listinfo.cgi/boost-users