Commit 1a6fcd39 authored by Robert Bradshaw's avatar Robert Bradshaw

C++ class member test.

parent 1e92f37a
...@@ -990,6 +990,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -990,6 +990,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
have_entries, (py_attrs, py_buffers, memoryview_slices) = \ have_entries, (py_attrs, py_buffers, memoryview_slices) = \
scope.get_refcounted_entries(include_weakref=True) scope.get_refcounted_entries(include_weakref=True)
cpp_class_attrs = [entry for entry in scope.var_entries if entry.type.is_cpp_class]
new_func_entry = scope.lookup_here("__new__") new_func_entry = scope.lookup_here("__new__")
if base_type or (new_func_entry and new_func_entry.is_special if base_type or (new_func_entry and new_func_entry.is_special
...@@ -998,7 +999,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -998,7 +999,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else: else:
unused_marker = 'CYTHON_UNUSED ' unused_marker = 'CYTHON_UNUSED '
need_self_cast = type.vtabslot_cname or have_entries need_self_cast = type.vtabslot_cname or have_entries or cpp_class_attrs
code.putln("") code.putln("")
code.putln( code.putln(
"static PyObject *%s(PyTypeObject *t, %sPyObject *a, %sPyObject *k) {" "static PyObject *%s(PyTypeObject *t, %sPyObject *a, %sPyObject *k) {"
...@@ -1036,9 +1037,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1036,9 +1037,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type.vtabslot_cname, type.vtabslot_cname,
struct_type_cast, type.vtabptr_cname)) struct_type_cast, type.vtabptr_cname))
for entry in scope.var_entries: for entry in cpp_class_attrs:
if entry.type.is_cpp_class: code.putln("new((void*)&(p->%s)) %s();" %
code.putln("new(&(p->%s)) %s();" % (entry.cname, entry.type.cname)); (entry.cname, entry.type.cname));
for entry in py_attrs: for entry in py_attrs:
if scope.is_internal or entry.name == "__weakref__": if scope.is_internal or entry.name == "__weakref__":
...@@ -1086,8 +1087,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1086,8 +1087,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
weakref_slot = scope.lookup_here("__weakref__") weakref_slot = scope.lookup_here("__weakref__")
_, (py_attrs, _, memoryview_slices) = scope.get_refcounted_entries() _, (py_attrs, _, memoryview_slices) = scope.get_refcounted_entries()
cpp_class_attrs = [entry for entry in scope.var_entries if entry.type.is_cpp_class]
if py_attrs or memoryview_slices or weakref_slot in scope.var_entries: if (py_attrs
or cpp_class_attrs
or memoryview_slices
or weakref_slot in scope.var_entries):
self.generate_self_cast(scope, code) self.generate_self_cast(scope, code)
# call the user's __dealloc__ # call the user's __dealloc__
...@@ -1095,9 +1100,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1095,9 +1100,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if weakref_slot in scope.var_entries: if weakref_slot in scope.var_entries:
code.putln("if (p->__weakref__) PyObject_ClearWeakRefs(o);") code.putln("if (p->__weakref__) PyObject_ClearWeakRefs(o);")
for entry in scope.var_entries: for entry in cpp_class_attrs:
if entry.type.is_cpp_class: class_name = entry.type.cname.split("::")[-1]
code.putln("p->%s.~%s();" % (entry.cname, entry.type.cname)); code.putln("p->%s.~%s();" % (entry.cname, class_name));
for entry in py_attrs: for entry in py_attrs:
code.put_xdecref("p->%s" % entry.cname, entry.type, nanny=False) code.put_xdecref("p->%s" % entry.cname, entry.type, nanny=False)
......
...@@ -1774,6 +1774,7 @@ class CClassScope(ClassScope): ...@@ -1774,6 +1774,7 @@ class CClassScope(ClassScope):
if constructor is not None and \ if constructor is not None and \
PyrexTypes.best_match([], constructor.all_alternatives()) is None: PyrexTypes.best_match([], constructor.all_alternatives()) is None:
error(pos, "C++ class must have a no-arg constructor to be a member of an extension type; use a pointer instead") error(pos, "C++ class must have a no-arg constructor to be a member of an extension type; use a pointer instead")
self.use_utility_code(Code.UtilityCode("#include <new>"))
entry = self.declare(name, cname, type, pos, visibility) entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1 entry.is_variable = 1
self.var_entries.append(entry) self.var_entries.append(entry)
......
...@@ -33,6 +33,9 @@ cdef extern from "shapes.h" namespace "shapes": ...@@ -33,6 +33,9 @@ cdef extern from "shapes.h" namespace "shapes":
int side int side
Square(int) Square(int)
cdef cppclass Empty(Shape):
pass
int constructor_count, destructor_count int constructor_count, destructor_count
def test_new_del(): def test_new_del():
...@@ -81,3 +84,22 @@ def test_value_call(int w): ...@@ -81,3 +84,22 @@ def test_value_call(int w):
return get_area(sqr[0]), get_area(rect[0]) return get_area(sqr[0]), get_area(rect[0])
finally: finally:
del sqr del sqr
cdef class EmptyHolder:
cdef Empty empty
def test_class_member():
"""
>>> test_class_member()
"""
start_constructor_count = constructor_count
start_destructor_count = destructor_count
e1 = EmptyHolder()
assert constructor_count - start_constructor_count == 1, \
constructor_count - start_constructor_count
e2 = EmptyHolder()
assert constructor_count - start_constructor_count == 2, \
constructor_count - start_constructor_count
del e1, e2
assert destructor_count - start_destructor_count == 2, \
destructor_count - start_destructor_count
...@@ -48,6 +48,10 @@ namespace shapes { ...@@ -48,6 +48,10 @@ namespace shapes {
int radius; int radius;
}; };
class Empty : public Shape {
float area() { return 0; }
};
} }
#endif #endif
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