Commit 8b80fda7 authored by Xavier Thompson's avatar Xavier Thompson

Let cclass wrapper tp_new build the underlying cypclass

parent 44f197c4
......@@ -1565,6 +1565,29 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"static PyObject *%s(PyTypeObject *t, %sPyObject *a, %sPyObject *k) {" % (
slot_func, unused_marker, unused_marker))
# for cyp wrappers, just allocate the cyobject and return the wrapper
# let the wrapped __init__ handle initialisation
if type.is_cyp_wrapper:
from .CypclassWrapper import generate_cypclass_wrapper_allocation
code.putln("if (t != %s) {" % type.typeptr_cname)
code.putln(
"PyErr_SetString(PyExc_TypeError,\"Cannot build a subtype of %s with %s.__new__\");"
% (scope.qualified_name, scope.qualified_name)
)
code.putln("return NULL;")
code.putln("}")
code.putln("CyObject * self = %s();" % type.wrapped_alloc)
generate_cypclass_wrapper_allocation(code, type)
code.putln(
"PyObject* wrapper = reinterpret_cast<PyObject *>(static_cast<%s *>(self));"
% Naming.cypclass_wrapper_layout_type
)
code.putln("Py_INCREF(wrapper);")
code.putln("return wrapper;")
code.putln("}")
return
need_self_cast = (type.vtabslot_cname or
(py_buffers or memoryview_slices or py_attrs) or
cpp_class_attrs or cyp_class_attrs)
......
......@@ -5588,6 +5588,9 @@ class CypclassWrapperDefNode(CClassDefNode):
self.wrapped_cypclass.entry.type.wrapper_type = self.entry.type
# > remember the declaration of the wrapped type
self.entry.type.wrapped_cname = self.wrapped_cypclass.entry.type.empty_declaration_code()
# > remember the cname of the wrapped type allocation function
alloc_entry = self.wrapped_cypclass.entry.type.scope.lookup_here("<alloc>")
self.entry.type.wrapped_alloc = alloc_entry.func_cname
class PropertyNode(StatNode):
......
......@@ -1501,12 +1501,14 @@ class PyExtensionType(PyObjectType):
# defered_declarations [thunk] Used to declare class hierarchies in order
# check_size 'warn', 'error', 'ignore' What to do if tp_basicsize does not match
# wrapped_cname string or None The full namespace declaration of the wrapped type when this is a cyp_wrapper
# wrapped_alloc string or None The cname of the wrapped type allocation function when this is a cyp_wrapper
is_extension_type = 1
has_attributes = 1
early_init = 1
wrapper_cname = None
wrapped_alloc = None
objtypedef_cname = None
......
......@@ -433,7 +433,8 @@ class ConstructorSlot(InternalMethodSlot):
and not scope.has_pyobject_attrs
and not scope.has_memoryview_attrs
and not scope.has_cpp_class_attrs
and not (self.slot_name == 'tp_new' and scope.parent_type.vtabslot_cname)):
and not (self.slot_name == 'tp_new' and scope.parent_type.vtabslot_cname)
and not (self.slot_name == 'tp_new' and scope.parent_type.is_cyp_wrapper)):
entry = scope.lookup_here(self.method) if self.method else None
if not (entry and entry.is_special):
return False
......
......@@ -209,16 +209,16 @@
static inline U* __Pyx_PyObject_AsCyObject(PyObject * ob, PyTypeObject * type) {
// the PyObject is not of the expected type
if (ob->ob_type != type) {
PyErr_SetString(PyExc_TypeError, "Conversion Error: Could not convert to CyObject");
PyErr_Format(PyExc_TypeError, "Cannot convert PyObject %s to CyObject %s", ob->ob_type->tp_name, type->tp_name);
return NULL;
}
CyPyObject * wrapper = (CyPyObject *)ob;
U * underlying = dynamic_cast<U *>(static_cast<CyObject *>(wrapper));
// no underlying cyobject: shouldn't happen, playing it safe for now
// failed dynamic cast: should not happen
if (underlying == NULL) {
PyErr_SetString(PyExc_TypeError, "Conversion Error: CyObject wrapper has no underlying CyObject");
PyErr_Format(PyExc_TypeError, "Could not convert %s PyObject wrapper to its underlying CyObject", type->tp_name);
return NULL;
}
......
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