Copy of a C++ object extended with Boost.Python
I have a simple C++ object, exposed to python with Boost.python, like this : ------------------------------------------------- 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 ?
On Mon, Aug 24, 2009 at 1:06 PM, 4ian
I have a simple C++ object, exposed to python with Boost.python, like this :
------------------------------------------------- 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 ?
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.
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 ?
On 24 août, 22:01, OvermindDL1
On Mon, Aug 24, 2009 at 1:06 PM, 4ian
wrote: I have a simple C++ object, exposed to python with Boost.python, like this :
------------------------------------------------- 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 ?
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. _______________________________________________ Boost-users mailing list Boost-us...@lists.boost.orghttp://lists.boost.org/mailman/listinfo.cgi/boost-users
On Tue, Aug 25, 2009 at 3:52 AM, 4ian
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).
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
On Tue, Aug 25, 2009 at 3:52 AM, 4ian
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
On Thu, Aug 27, 2009 at 10:46 AM, 4ian
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
wrote: On Tue, Aug 25, 2009 at 3:52 AM, 4ian
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
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
On Thu, Aug 27, 2009 at 10:46 AM, 4ian
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
wrote: On Tue, Aug 25, 2009 at 3:52 AM, 4ian
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...@lists.boost.orghttp://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
4ian
-
OvermindDL1