Commit 568bcc0c authored by Robert Bradshaw's avatar Robert Bradshaw

Fix generation of api code for C++ classes with object members.

Fixes Github issue #1886.
parent 9c6af17f
...@@ -901,6 +901,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -901,6 +901,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.put("virtual ") code.put("virtual ")
has_virtual_methods = True has_virtual_methods = True
code.putln("%s;" % attr.type.declaration_code(attr.cname)) code.putln("%s;" % attr.type.declaration_code(attr.cname))
is_implementing = 'init_module' in code.globalstate.parts
if constructor or py_attrs: if constructor or py_attrs:
if constructor: if constructor:
arg_decls = [] arg_decls = []
...@@ -917,51 +918,61 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -917,51 +918,61 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else: else:
arg_decls = ["void"] arg_decls = ["void"]
arg_names = [] arg_names = []
code.putln("%s(%s) {" % (type.cname, ", ".join(arg_decls))) if is_implementing:
if py_attrs: code.putln("%s(%s) {" % (type.cname, ", ".join(arg_decls)))
code.put_ensure_gil() if py_attrs:
for attr in py_attrs: code.put_ensure_gil()
code.put_init_var_to_py_none(attr, nanny=False); for attr in py_attrs:
if constructor: code.put_init_var_to_py_none(attr, nanny=False);
code.putln("%s(%s);" % (constructor.cname, ", ".join(arg_names))) if constructor:
if py_attrs: code.putln("%s(%s);" % (constructor.cname, ", ".join(arg_names)))
code.put_release_ensured_gil() if py_attrs:
code.putln("}") code.put_release_ensured_gil()
code.putln("}")
else:
code.putln("%s(%s);" % (type.cname, ", ".join(arg_decls)))
if destructor or py_attrs or has_virtual_methods: if destructor or py_attrs or has_virtual_methods:
if has_virtual_methods: if has_virtual_methods:
code.put("virtual ") code.put("virtual ")
code.putln("~%s() {" % type.cname) if is_implementing:
if py_attrs: code.putln("~%s() {" % type.cname)
code.put_ensure_gil() if py_attrs:
if destructor: code.put_ensure_gil()
code.putln("%s();" % destructor.cname) if destructor:
if py_attrs: code.putln("%s();" % destructor.cname)
for attr in py_attrs: if py_attrs:
code.put_var_xdecref(attr, nanny=False); for attr in py_attrs:
code.put_release_ensured_gil() code.put_var_xdecref(attr, nanny=False);
code.putln("}") code.put_release_ensured_gil()
code.putln("}")
else:
code.putln("~%s();" % type.cname)
if py_attrs: if py_attrs:
# Also need copy constructor and assignment operators. # Also need copy constructor and assignment operators.
code.putln("%s(const %s& __Pyx_other) {" % (type.cname, type.cname)) if is_implementing:
code.put_ensure_gil() code.putln("%s(const %s& __Pyx_other) {" % (type.cname, type.cname))
for attr in scope.var_entries: code.put_ensure_gil()
if not attr.type.is_cfunction: for attr in scope.var_entries:
code.putln("%s = __Pyx_other.%s;" % (attr.cname, attr.cname)) if not attr.type.is_cfunction:
code.put_var_incref(attr, nanny=False) code.putln("%s = __Pyx_other.%s;" % (attr.cname, attr.cname))
code.put_release_ensured_gil() code.put_var_incref(attr, nanny=False)
code.putln("}") code.put_release_ensured_gil()
code.putln("%s& operator=(const %s& __Pyx_other) {" % (type.cname, type.cname)) code.putln("}")
code.putln("if (this != &__Pyx_other) {") code.putln("%s& operator=(const %s& __Pyx_other) {" % (type.cname, type.cname))
code.put_ensure_gil() code.putln("if (this != &__Pyx_other) {")
for attr in scope.var_entries: code.put_ensure_gil()
if not attr.type.is_cfunction: for attr in scope.var_entries:
code.put_var_xdecref(attr, nanny=False); if not attr.type.is_cfunction:
code.putln("%s = __Pyx_other.%s;" % (attr.cname, attr.cname)) code.put_var_xdecref(attr, nanny=False);
code.put_var_incref(attr, nanny=False) code.putln("%s = __Pyx_other.%s;" % (attr.cname, attr.cname))
code.put_release_ensured_gil() code.put_var_incref(attr, nanny=False)
code.putln("}") code.put_release_ensured_gil()
code.putln("return *this;") code.putln("}")
code.putln("}") code.putln("return *this;")
code.putln("}")
else:
code.putln("%s(const %s& __Pyx_other);" % (type.cname, type.cname))
code.putln("%s& operator=(const %s& __Pyx_other);" % (type.cname, type.cname))
code.putln("};") code.putln("};")
def generate_enum_definition(self, entry, code): def generate_enum_definition(self, entry, code):
......
...@@ -226,6 +226,18 @@ def test_CppClassWithObjectMemberCopyAssign(name): ...@@ -226,6 +226,18 @@ def test_CppClassWithObjectMemberCopyAssign(name):
print "Nothing alive." print "Nothing alive."
# Github issue #1886.
cdef public cppclass PublicCppClassWithObjectMember:
object o
def test_PublicCppClassWithObjectMember():
"""
>>> test_PublicCppClassWithObjectMember()
"""
cdef PublicCppClassWithObjectMember c
assert c.o is None
cdef cppclass UncopyableConstructorArgument: cdef cppclass UncopyableConstructorArgument:
unique_ptr[vector[int]] member unique_ptr[vector[int]] member
__init__(unique_ptr[vector[int]] arg): __init__(unique_ptr[vector[int]] arg):
......
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