[C++-sig] how to deep copy boost python object
Matthew Scouten (TT)
Matthew.Scouten at tradingtechnologies.com
Mon May 11 18:31:41 CEST 2009
If you make an object pickleable, you get deepcopy for free, because the
deepcopy function will use a pickle-unpickle cycle as a fall back if it
cannot find any other way to copy. This has the disadvantage that you
must come up with a sensible pickled representation, and you pay for a
round trip through a string. This is especially annoying since all c++
objects are already deepcopyable by default: just use a call copy-ctor.
There is another way to tell python how to deepcopy an object: give it a
__deepcopy__ function (and a __copy__ function).
This is some code I got from Hans Meine a while back:
#define PYTHON_ERROR(TYPE, REASON) \
{ \
PyErr_SetString(TYPE, REASON); \
throw bp::error_already_set(); \
}
template<class T>
inline PyObject * managingPyObject(T *p)
{
return typename bp::manage_new_object::apply<T *>::type()(p);
}
template<class Copyable>
bp::object
generic__copy__(bp::object copyable)
{
Copyable *newCopyable(new Copyable(bp::extract<const Copyable
&>(copyable)));
bp::object
result(bp::detail::new_reference(managingPyObject(newCopyable)));
bp::extract<bp::dict>(result.attr("__dict__"))().update(
copyable.attr("__dict__"));
return result;
}
template<class Copyable>
bp::object
generic__deepcopy__(bp::object copyable, bp::dict memo)
{
bp::object copyMod = bp::import("copy");
bp::object deepcopy = copyMod.attr("deepcopy");
Copyable *newCopyable(new Copyable(bp::extract<const Copyable
&>(copyable)));
bp::object
result(bp::detail::new_reference(managingPyObject(newCopyable)));
// HACK: copyableId shall be the same as the result of id(copyable)
in Python -
// please tell me that there is a better way! (and which ;-p)
int copyableId = (int)(copyable.ptr());
memo[copyableId] = result;
bp::extract<bp::dict>(result.attr("__dict__"))().update(
deepcopy(bp::extract<bp::dict>(copyable.attr("__dict__"))(),
memo));
return result;
}
To use it:
class_<foo>(foo)
.def("__copy__", &generic__copy__< foo >)
.def("__deepcopy__", &generic__deepcopy__< foo >)
.def(init< const foo & >())
This has the advantage that you can use it on any existing class that
has a sensible cctor.
-----Original Message-----
From:
cplusplus-sig-bounces+matthew.scouten=tradingtechnologies.com at python.org
[mailto:cplusplus-sig-bounces+matthew.scouten=tradingtechnologies.com at py
thon.org] On Behalf Of Gennadiy Rozental
Sent: Monday, May 11, 2009 12:47 AM
To: cplusplus-sig at python.org
Subject: Re: [C++-sig] how to deep copy boost python object
Ralf W. Grosse-Kunstleve <rwgk <at> yahoo.com> writes:
>
>
> A comprehensive approach is to make the object picklable.
> As a side-effect, copy.deepcopy() will also work.
1. Are you saying that copy.deepcopy does not work without object being
picklable? What will happend if I try to use it for non picklable
object?
2. What if object IS picklable. How will invoke deepcopy operation on
bp::object?
Gennadiy
_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig at python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig
More information about the Cplusplus-sig
mailing list