[C++-sig] How about class_<...>.enable_copy() ?
meine at informatik.uni-hamburg.de
Mon Jul 23 19:22:15 CEST 2007
I still have the same problem as last time, that I want to be able to
copy.copy(foo) and copy.deepcopy(foo) my BPL-exported objects:
Am Freitag, 08. Juni 2007 17:06:36 schrieb Hans Meine:
> This works if pickling support has been explicitly coded, by pickling and
> unpickling. It would be neat if there was an .enable_copy() or sth. like
> that, which would define a __copy__ (or __deepcopy__) method that simply
> calls the copy constructor. That would be more efficient than the pickling
> approach, both at runtime and in terms of saved LOCs. Have you thought
> about such a thing? Is there a common short idiom that does that already?
> Is there a rationale for not providing copying support?
Ralf answered (thanks BTW) that I should export the copy constructor.
I think that is not a bad idea, but I would ideally like to have:
foo = Foo(other) # copy constructor as in C++ (1)
foo = copy.copy(other) # pythonic copying (2)
foo = copy.deepcopy(other) # deepcopying (3)
(1) is easy to do by exporting the copy constructor
(2) could be implemented by setting __copy__ to the above copy constructor,
but one would assume __dict__ to be (non-deep)copied, too.
(3) definitely needs its own implementation, which needs to call deepcopy
I would still believe that an .enable_copy() would be very handy. It could
possibly be controlled by an enum arg which of the above methods should be
I tried to implement (2) and (3) manually today, but failed. Mostly because I
am not 100% sure how to mix Python C API and BPL code correctly. I have the
following general questions:
A) How do I convert a Foo * into a boost::python::object if I exported the Foo
class? Back in those days when I first used BPLv2, I wrote the
following "nifty" function:
inline PyObject * managingPyObject(T *p)
return typename manage_new_object::apply<T *>::type()(p);
Is there a better way? Also, this only gives me a PyObject *, which brings me
to my next question:
B) How do I convert PyObject * into a boost::python::object if it's a new
reference? Is this boost::python::detail::new_reference? Why is this
in "detail" then?
C) How do I convert PyObject * into a boost::python::object if it's a borrowed
reference? I guess that handle(borrowed(...)) helps here?
Finally, I wonder whether nobody else tried to implement __deepcopy__ with BPL
yet - I could not find anything useful, searching the WWW for >2 hours now.
I tried to get the copy.deepcopy function which I need to call recursively
PyObject* pyDeepcopy =
Py_file_input, Py_None, Py_None);
bp::call<bp::dict>(pyDeepcopy, map.attr("__dict__"), memo));
Unfortunatly, with empty globals and locals, __import__ is not found. :-(
Probably I should use PyImport_ImportModule or the new boost::python::import.
That seems to work, but the recursive call then fails:
File "/software/python-2.4.4/lib/python2.4/copy.py", line 185, in deepcopy
y = copier(x, memo)
TypeError: No to_python (by-value) converter found for C++ type:
The code (which relies on 1.34.0) now looks like this (see attachment):
bp::object Foo__deepcopy__(bp::object foo, bp::dict memo)
bp::object copyMod = bp::import("copy");
bp::object deepcopy = copyMod.attr("deepcopy");
Foo *newFoo(new Foo(bp::extract<const Foo &>(foo)));
Ciao, / /
/ / ANS
-------------- next part --------------
A non-text attachment was scrubbed...
Size: 838 bytes
Desc: not available
More information about the Cplusplus-sig