Commit cbc3c84c authored by Robert Bradshaw's avatar Robert Bradshaw

Add required copy and assignment operators for C++ classes with python object attributes.

parent 2cad794f
......@@ -1916,9 +1916,12 @@ class CCodeWriter(object):
if entry.type.is_pyobject:
self.putln("__Pyx_XGIVEREF(%s);" % self.entry_as_pyobject(entry))
def put_var_incref(self, entry):
def put_var_incref(self, entry, nanny=True):
if entry.type.is_pyobject:
if nanny:
self.putln("__Pyx_INCREF(%s);" % self.entry_as_pyobject(entry))
else:
self.putln("Py_INCREF(%s);" % self.entry_as_pyobject(entry))
def put_var_xincref(self, entry):
if entry.type.is_pyobject:
......
......@@ -951,6 +951,28 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.put_var_xdecref(attr, nanny=False);
code.put_release_ensured_gil()
code.putln("}")
if py_attrs:
# Also need copy constructor and assignment operators.
code.putln("%s(const %s& __Pyx_other) {" % (type.cname, type.cname))
code.put_ensure_gil()
for attr in scope.var_entries:
if not attr.type.is_cfunction:
code.putln("%s = __Pyx_other.%s;" % (attr.cname, attr.cname))
code.put_var_incref(attr, nanny=False)
code.put_release_ensured_gil()
code.putln("}")
code.putln("%s& operator=(const %s& __Pyx_other) {" % (type.cname, type.cname))
code.putln("if (this != &__Pyx_other) {")
code.put_ensure_gil()
for attr in scope.var_entries:
if not attr.type.is_cfunction:
code.put_var_xdecref(attr, nanny=False);
code.putln("%s = __Pyx_other.%s;" % (attr.cname, attr.cname))
code.put_var_incref(attr, nanny=False)
code.put_release_ensured_gil()
code.putln("}")
code.putln("return *this;")
code.putln("}")
code.putln("};")
def generate_enum_definition(self, entry, code):
......
......@@ -6,6 +6,8 @@ cdef double pi
from math import pi
from libc.math cimport sin, cos
from libcpp cimport bool
from libcpp.vector cimport vector
from cython.operator cimport dereference as deref
cdef extern from "shapes.h" namespace "shapes":
cdef cppclass Shape:
......@@ -163,6 +165,8 @@ cdef class NoisyAlloc(object):
print "NoisyAlloc.__dealloc__", self.name
except:
pass # Suppress unraisable exception warning.
def __repr__(self):
return "NoisyAlloc[%s]" % self.name
cdef cppclass CppClassWithObjectMember:
NoisyAlloc o
......@@ -188,3 +192,33 @@ def test_CppClassWithObjectMember(name):
"""
x = new CppClassWithObjectMember(name)
del x
def test_CppClassWithObjectMemberCopyAssign(name):
"""
>>> test_CppClassWithObjectMemberCopyAssign("gretel")
CppClassWithObjectMember.__init__ gretel
NoisyAlloc.__init__ gretel
CppClassWithObjectMember.__dealloc__ gretel
Alive in vector NoisyAlloc[gretel]
CppClassWithObjectMember.__init__ leterg
NoisyAlloc.__init__ leterg
NoisyAlloc.__dealloc__ gretel
CppClassWithObjectMember.__dealloc__ leterg
Alive in vector NoisyAlloc[leterg]
CppClassWithObjectMember.__dealloc__ leterg
NoisyAlloc.__dealloc__ leterg
Nothing alive.
"""
x = new CppClassWithObjectMember(name)
cdef vector[CppClassWithObjectMember] v
# Invokes copy constructor.
v.push_back(deref(x))
del x
print "Alive in vector", v[0].o
y = new CppClassWithObjectMember(name[::-1])
# Invokes copy assignment.
v[0] = deref(y)
del y
print "Alive in vector", v[0].o
v.clear()
print "Nothing alive."
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment