[C++-sig] Properly copying wrapped classes
Jim Bosch
jbosch at astro.princeton.edu
Sun Jun 3 17:25:38 CEST 2012
On 05/31/2012 08:49 PM, Jay Riley wrote:
> I'm having a problem with some python objects derived in python. I have
> a Clone method that's supposed to make a full copy of these python
> inherited objects, but it isn't working. The problem is my wrapper
> class' PyObject* self isn't getting copied, so when I use
> call_method<>(self, "method name"), self will never point to the copied
> instance. Here's a brief example showing the issue
>
<snip>
>
> Sorry about the length, just want to make sure I got everything relevant
> in. When I run this code, it prints:
>
> Python Clone
> Python Side Test. ID: 1
> Python Side Test. ID: 1
> Original ID 1
> Clone ID 1
>
> this is wrong because Clone ID should be 2 (inspecting the object
> confirms it is 2). Like I said I'm pretty sure the problem is that the
> wrapper class' copy constructor only makes a copy of the PyObject* self,
> not a full copy. This is how every reference doc I saw was doing class
> wrapping, but isn't this wrong? Should we be making a full copy of the
> PyObject*? How would I go about doing that, or otherwise modifying my
> classes to get the behaviour I expect.
>
There are a couple of things here that probably need to be addressed:
- Be wary of relying on copy-constructor side effects to demonstrate
whether something is working; the compiler is allowed to elide copy
constructors under many conditions, which might result in misleading
results. That said, I don't think that's what's causing your problem
here (or at least not all of it).
- Your implementations of __copy__ and __deepcopy__ won't work with
polymorphic wrapper classes, because they construct a BaseClass instance
and tell Boost.Python to wrap it by managing the new reference. That
necessarily makes a Python object that holds a BaseClass object, not one
that holds a BaseClassWrap object. If you want to get a BaseClassWrap
Python object, you want to pass it by value to Boost.Python; that should
invoke the BaseClassWrap copy constructor and pass it a new PyObject* to
manage (so it doesn't have to copy the PyObject* itself).
I think that just means you can remove the "managingPyObject" function,
and instead use:
object result(extract<const Copyable &>(copyable)());
HTH
Jim
More information about the Cplusplus-sig
mailing list