Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
411e944a
Commit
411e944a
authored
Jun 08, 2020
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cast underlying cyobject to base type and back safely instead of void *
parent
6411a8f8
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
44 additions
and
16 deletions
+44
-16
Cython/Compiler/CypclassWrapper.py
Cython/Compiler/CypclassWrapper.py
+17
-7
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+2
-2
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+11
-7
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+14
-0
No files found.
Cython/Compiler/CypclassWrapper.py
View file @
411e944a
...
@@ -237,12 +237,20 @@ class CypclassWrapperInjection(CythonTransform):
...
@@ -237,12 +237,20 @@ class CypclassWrapperInjection(CythonTransform):
return
wrapper
return
wrapper
def
synthesize_underlying_cyobject_attribute
(
self
,
node
):
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
,
node
.
pos
,
name
=
"void"
,
name
=
base_type
.
name
,
module_path
=
[]
,
module_path
=
nesting_path
,
is_basic_c_type
=
1
,
is_basic_c_type
=
0
,
signed
=
1
,
signed
=
1
,
complex
=
0
,
complex
=
0
,
longness
=
0
,
longness
=
0
,
...
@@ -251,12 +259,11 @@ class CypclassWrapperInjection(CythonTransform):
...
@@ -251,12 +259,11 @@ class CypclassWrapperInjection(CythonTransform):
)
)
underlying_name_declarator
=
Nodes
.
CNameDeclaratorNode
(
node
.
pos
,
name
=
underlying_name
,
cname
=
None
)
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
(
underlying_cyobject
=
Nodes
.
CVarDefNode
(
pos
=
node
.
pos
,
pos
=
node
.
pos
,
visibility
=
'private'
,
visibility
=
'private'
,
base_type
=
void
_type_node
,
base_type
=
base
_type_node
,
declarators
=
[
underlying_name_declarator
],
declarators
=
[
underlying_name_declarator
],
in_pxd
=
node
.
in_pxd
,
in_pxd
=
node
.
in_pxd
,
doc
=
None
,
doc
=
None
,
...
@@ -765,11 +772,14 @@ def generate_cyp_class_wrapper_definition(type, wrapper_entry, constructor_entry
...
@@ -765,11 +772,14 @@ def generate_cyp_class_wrapper_definition(type, wrapper_entry, constructor_entry
# initialise PyObject fields
# initialise PyObject fields
if
is_new_return_type
and
type
.
wrapper_type
:
if
is_new_return_type
and
type
.
wrapper_type
:
chain_casted_self
=
"self"
for
first_base
in
type
.
first_base_iter
():
chain_casted_self
=
"static_cast<%s *>(%s)"
%
(
first_base
.
empty_declaration_code
(),
chain_casted_self
)
objstruct_cname
=
type
.
wrapper_type
.
objstruct_cname
objstruct_cname
=
type
.
wrapper_type
.
objstruct_cname
cclass_wrapper_base
=
type
.
wrapped_base_type
.
wrapper_type
cclass_wrapper_base
=
type
.
wrapped_base_type
.
wrapper_type
code
.
putln
(
"if(self) {"
)
code
.
putln
(
"if(self) {"
)
code
.
putln
(
"%s * wrapper = new %s();"
%
(
objstruct_cname
,
objstruct_cname
))
code
.
putln
(
"%s * wrapper = new %s();"
%
(
objstruct_cname
,
objstruct_cname
))
code
.
putln
(
"((%s *)wrapper)->nogil_cyobject =
self;"
%
cclass_wrapper_base
.
objstruct_cname
)
code
.
putln
(
"((%s *)wrapper)->nogil_cyobject =
%s;"
%
(
cclass_wrapper_base
.
objstruct_cname
,
chain_casted_self
)
)
code
.
putln
(
"PyObject * wrapper_as_py = (PyObject *) wrapper;"
)
code
.
putln
(
"PyObject * wrapper_as_py = (PyObject *) wrapper;"
)
code
.
putln
(
"wrapper_as_py->ob_refcnt = 0;"
)
code
.
putln
(
"wrapper_as_py->ob_refcnt = 0;"
)
code
.
putln
(
"wrapper_as_py->ob_type = %s;"
%
type
.
wrapper_type
.
typeptr_cname
)
code
.
putln
(
"wrapper_as_py->ob_type = %s;"
%
type
.
wrapper_type
.
typeptr_cname
)
...
...
Cython/Compiler/ModuleNode.py
View file @
411e944a
...
@@ -1402,7 +1402,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -1402,7 +1402,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# internal classes (should) never need None inits, normal zeroing will do
# internal classes (should) never need None inits, normal zeroing will do
py_attrs
=
[]
py_attrs
=
[]
#
cyp_class attributes should not be treated as normal cpp_class attribute
s
#
unlike normal cpp_class attributes, cyp_class attributes are always held as pointer
s
cpp_class_attrs
=
[
entry
for
entry
in
scope
.
var_entries
cpp_class_attrs
=
[
entry
for
entry
in
scope
.
var_entries
if
entry
.
type
.
is_cpp_class
and
not
entry
.
type
.
is_cyp_class
]
if
entry
.
type
.
is_cpp_class
and
not
entry
.
type
.
is_cyp_class
]
...
@@ -1582,7 +1582,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -1582,7 +1582,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
_
,
(
py_attrs
,
_
,
memoryview_slices
)
=
scope
.
get_refcounted_entries
()
_
,
(
py_attrs
,
_
,
memoryview_slices
)
=
scope
.
get_refcounted_entries
()
#
cyp_class attributes should not be treated as normal cpp_class attribute
s
#
unlike normal cpp_class attributes, cyp_class attributes are always held as pointer
s
cpp_class_attrs
=
[
entry
for
entry
in
scope
.
var_entries
cpp_class_attrs
=
[
entry
for
entry
in
scope
.
var_entries
if
entry
.
type
.
is_cpp_class
and
not
entry
.
type
.
is_cyp_class
]
if
entry
.
type
.
is_cpp_class
and
not
entry
.
type
.
is_cyp_class
]
...
...
Cython/Compiler/Nodes.py
View file @
411e944a
...
@@ -5457,13 +5457,17 @@ class CypclassWrapperDefNode(CClassDefNode):
...
@@ -5457,13 +5457,17 @@ class CypclassWrapperDefNode(CClassDefNode):
# > access the underlying cyobject from the self argument of the wrapper method
# > 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
)
underlying_obj
=
ExprNodes
.
AttributeNode
(
cfunc_method
.
pos
,
obj
=
self_obj
,
attribute
=
underlying_name
)
empty_declarator
=
CNameDeclaratorNode
(
cfunc_method
.
pos
,
name
=
""
,
cname
=
None
)
cast_operation
=
ExprNodes
.
TypecastNode
(
# > cast the underlying object back to this type
cfunc_method
.
pos
,
underlying_type
=
self
.
wrapped_cypclass
.
entry
.
type
type
=
self
.
wrapped_cypclass
.
entry
.
type
,
cast_operation
=
underlying_obj
operand
=
underlying_obj
,
for
derived_type
in
underlying_type
.
first_base_rev_iter
():
typecheck
=
False
cast_operation
=
ExprNodes
.
TypecastNode
(
)
cfunc_method
.
pos
,
type
=
derived_type
,
operand
=
cast_operation
,
typecheck
=
False
)
cast_underlying_obj
=
ExprNodes
.
NameNode
(
self_pos
,
name
=
EncodedString
(
"cast_cyobject"
))
cast_underlying_obj
=
ExprNodes
.
NameNode
(
self_pos
,
name
=
EncodedString
(
"cast_cyobject"
))
cast_assignment
=
SingleAssignmentNode
(
self_pos
,
lhs
=
cast_underlying_obj
,
rhs
=
cast_operation
)
cast_assignment
=
SingleAssignmentNode
(
self_pos
,
lhs
=
cast_underlying_obj
,
rhs
=
cast_operation
)
...
...
Cython/Compiler/PyrexTypes.py
View file @
411e944a
...
@@ -4050,6 +4050,20 @@ class CypClassType(CppClassType):
...
@@ -4050,6 +4050,20 @@ class CypClassType(CppClassType):
self
.
_left_path_to_base
[
base
]
=
path
self
.
_left_path_to_base
[
base
]
=
path
return
path
return
path
# 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
# allow conversion to Python only when there is a wrapper type
def
can_coerce_to_pyobject
(
self
,
env
):
def
can_coerce_to_pyobject
(
self
,
env
):
return
self
.
wrapper_type
is
not
None
return
self
.
wrapper_type
is
not
None
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment