Commit a50b90e3 authored by Xavier Thompson's avatar Xavier Thompson

Cast underlying cyobject to base type and back safely instead of void *

parent 4a3646d1
......@@ -237,12 +237,20 @@ class CypclassWrapperInjection(CythonTransform):
return wrapper
def synthesize_underlying_cyobject_attribute(self, node):
base_type = node.entry.type.wrapped_base_type
void_type_node = Nodes.CSimpleBaseTypeNode(
nesting_path = []
outer_scope = base_type.scope.outer_scope
while outer_scope and not outer_scope.is_module_scope:
nesting_path.append(outer_scope.name)
outer_scope = outer_scope.outer_scope
nesting_path.reverse()
base_type_node = Nodes.CSimpleBaseTypeNode(
node.pos,
name = "void",
module_path = [],
is_basic_c_type = 1,
name = base_type.name,
module_path = nesting_path,
is_basic_c_type = 0,
signed = 1,
complex = 0,
longness = 0,
......@@ -251,12 +259,11 @@ class CypclassWrapperInjection(CythonTransform):
)
underlying_name_declarator = Nodes.CNameDeclaratorNode(node.pos, name=underlying_name, cname=None)
underlying_name_declarator = Nodes.CPtrDeclaratorNode(node.pos, base=underlying_name_declarator)
underlying_cyobject = Nodes.CVarDefNode(
pos = node.pos,
visibility = 'private',
base_type = void_type_node,
base_type = base_type_node,
declarators = [underlying_name_declarator],
in_pxd = node.in_pxd,
doc = None,
......
......@@ -1514,7 +1514,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# internal classes (should) never need None inits, normal zeroing will do
py_attrs = []
# cyp_class attributes should not be treated as normal cpp_class attributes
# unlike normal cpp_class attributes, cyp_class attributes are always held as pointers
cpp_class_attrs = [entry for entry in scope.var_entries
if entry.type.is_cpp_class and not entry.type.is_cyp_class]
......@@ -1713,7 +1713,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
_, (py_attrs, _, memoryview_slices) = scope.get_refcounted_entries()
# cyp_class attributes should not be treated as normal cpp_class attributes
# unlike normal cpp_class attributes, cyp_class attributes are always held as pointers
cpp_class_attrs = [entry for entry in scope.var_entries
if entry.type.is_cpp_class and not entry.type.is_cyp_class]
......
......@@ -5668,10 +5668,12 @@ class CypclassWrapperDefNode(CClassDefNode):
# > access the underlying cyobject from the self argument of the wrapper method
underlying_obj = ExprNodes.AttributeNode(cfunc_method.pos, obj=self_obj, attribute=underlying_name)
empty_declarator = CNameDeclaratorNode(cfunc_method.pos, name="", cname=None)
# > cast the underlying object back to this type
underlying_type = self.wrapped_cypclass.entry.type
cast_operation = ExprNodes.TypecastNode(
cfunc_method.pos,
type = self.wrapped_cypclass.entry.type,
type = underlying_type,
operand = underlying_obj,
typecheck = False
)
......
......@@ -4231,6 +4231,20 @@ class CypClassType(CppClassType):
self._mro = mro_C3_merge(inputs)
return self._mro
# iterate over the chain of first wrapped bases until the oldest wrapped base is reached
def first_base_iter(self):
type_item = self
while type_item is not self.wrapped_base_type:
type_item = type_item.first_wrapped_base
yield type_item
# iterate down the chain of first wrapped bases until this type is reached
def first_base_rev_iter(self):
if self is not self.wrapped_base_type:
for t in self.first_wrapped_base.first_base_rev_iter():
yield t
yield self
# allow conversion to Python only when there is a wrapper type
def can_coerce_to_pyobject(self, env):
return self.wrapper_type is not None
......
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