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
4516a118
Commit
4516a118
authored
Jun 26, 2020
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use a POD struct defining the memory layout of wrappers to access the underlying cyobject
parent
394ab718
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
44 additions
and
38 deletions
+44
-38
Cython/Compiler/CypclassWrapper.py
Cython/Compiler/CypclassWrapper.py
+19
-13
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+1
-1
Cython/Compiler/Naming.py
Cython/Compiler/Naming.py
+6
-2
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+3
-19
Cython/Utility/CyObjects.cpp
Cython/Utility/CyObjects.cpp
+15
-3
No files found.
Cython/Compiler/CypclassWrapper.py
View file @
4516a118
...
...
@@ -294,7 +294,7 @@ def NAME(self, ARGDECLS):
stats
=
[]
if
not
cclass_bases
.
args
:
# the memory layout for the underlying cyobject should always be the same
#
-> maybe use a single common base cclass in the future
#
and match the memory layout of CyPyObject.
underlying_cyobject
=
self
.
synthesize_underlying_cyobject_attribute
(
node
)
stats
.
append
(
underlying_cyobject
)
...
...
@@ -344,7 +344,7 @@ def NAME(self, ARGDECLS):
underlying_name_declarator
=
Nodes
.
CNameDeclaratorNode
(
node
.
pos
,
name
=
underlying_name
,
cname
=
Naming
.
cypclass_
attr_cname
cname
=
Naming
.
cypclass_
wrapper_underlying_attr
)
underlying_cyobject
=
Nodes
.
CVarDefNode
(
...
...
@@ -1023,18 +1023,9 @@ def generate_cyp_class_wrapper_definition(type, wrapper_entry, constructor_entry
# __new__ can be defined by user and return another type
is_new_return_type
=
not
new_entry
or
new_entry
.
type
.
return_type
==
type
# initialise PyObject fields
#
allocate and
initialise PyObject fields
if
is_new_return_type
and
type
.
wrapper_type
:
objstruct_cname
=
type
.
wrapper_type
.
objstruct_cname
cclass_wrapper_base
=
type
.
wrapped_base_type
().
wrapper_type
code
.
putln
(
"if(self) {"
)
code
.
putln
(
"%s * wrapper = (%s *) ::operator new(sizeof *wrapper);"
%
(
objstruct_cname
,
objstruct_cname
))
code
.
putln
(
"((%s *)wrapper)->%s = self;"
%
(
cclass_wrapper_base
.
objstruct_cname
,
Naming
.
cypclass_attr_cname
))
code
.
putln
(
"PyObject * wrapper_as_py = (PyObject *) wrapper;"
)
code
.
putln
(
"wrapper_as_py->ob_refcnt = 0;"
)
code
.
putln
(
"wrapper_as_py->ob_type = %s;"
%
type
.
wrapper_type
.
typeptr_cname
)
code
.
putln
(
"self->cy_pyobject = wrapper_as_py;"
)
code
.
putln
(
"}"
)
generate_cypclass_wrapper_allocation
(
code
,
type
.
wrapper_type
)
if
init_entry
:
init_entry
=
PyrexTypes
.
best_match
(
wrapper_arg_types
,
...
...
@@ -1124,3 +1115,18 @@ def generate_cyp_class_wrapper_definition(type, wrapper_entry, constructor_entry
code
.
putln
(
"return self;"
)
code
.
putln
(
"}"
)
def
generate_cypclass_wrapper_allocation
(
code
,
wrapper_type
):
"""
Generate allocation and essential setup of the wrapper object.
The cname of the cyobject is assumed to be 'self'.
The cname 'wrapper' is assumed to be available.
"""
objstruct_cname
=
wrapper_type
.
objstruct_cname
code
.
putln
(
"if (self) {"
)
code
.
putln
(
"%s * wrapper = (%s *) ::operator new(sizeof *wrapper);"
%
(
objstruct_cname
,
objstruct_cname
))
code
.
putln
(
"((PyObject *)wrapper)->ob_refcnt = 0;"
)
code
.
putln
(
"((PyObject *)wrapper)->ob_type = %s;"
%
wrapper_type
.
typeptr_cname
)
code
.
putln
(
"((%s *)wrapper)->%s = self;"
%
(
Naming
.
cypclass_wrapper_layout_type
,
Naming
.
cypclass_wrapper_underlying_attr
))
code
.
putln
(
"self->cy_pyobject = (PyObject *) wrapper;"
)
code
.
putln
(
"}"
)
Cython/Compiler/ModuleNode.py
View file @
4516a118
...
...
@@ -1686,7 +1686,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# for cyp wrappers, just decrement the atomic counter of the underlying type
parent_type
=
scope
.
parent_type
if
parent_type
.
is_cyp_wrapper
:
underlying_attribute_name
=
Naming
.
cypclass_
attr_cname
underlying_attribute_name
=
Naming
.
cypclass_
wrapper_underlying_attr
self
.
generate_self_cast
(
scope
,
code
)
code
.
putln
(
"CyObject * p_nogil_cyobject = p->%s;"
...
...
Cython/Compiler/Naming.py
View file @
4516a118
...
...
@@ -166,8 +166,12 @@ exc_vars = (exc_type_name, exc_value_name, exc_tb_name)
api_name
=
pyrex_prefix
+
"capi__"
# c name for underlying cypclass attribute in cypclass wrappers
cypclass_attr_cname
=
"nogil_cyobject"
# cname for the type that defines the essential memory layout of a cypclass wrapper.
cypclass_wrapper_layout_type
=
"CyPyObject"
# cname for the underlying cypclass attribute in the memory layout of a cypclass wrapper.
cypclass_wrapper_underlying_attr
=
"nogil_cyobject"
# the h and api guards get changed to:
# __PYX_HAVE__FILENAME (for ascii filenames)
...
...
Cython/Compiler/PyrexTypes.py
View file @
4516a118
...
...
@@ -4180,7 +4180,6 @@ class CypClassType(CppClassType):
# _mro [CppClassType] or None the Method Resolution Order of this cypclass according to Python
# support_wrapper boolean whether this cypclass will be wrapped
# wrapper_type PyExtensionType or None the type of the cclass wrapper
# _wrapped_base_type CypClassType or None the type of the oldest wrapped cypclass base
is_cyp_class
=
1
to_py_function
=
None
...
...
@@ -4195,20 +4194,6 @@ class CypClassType(CppClassType):
self
.
wrapper_type
=
None
self
.
_wrapped_base_type
=
None
# return the oldest left-path superclass such that all intervening classes have a wrapper
def
wrapped_base_type
(
self
):
# if the result has already been computed, return it
if
self
.
_wrapped_base_type
is
not
None
:
return
self
.
_wrapped_base_type
# find the first wrapped base (if there is one) and take the same oldest superclass
for
base_type
in
self
.
base_classes
:
if
base_type
.
is_cyp_class
and
base_type
.
support_wrapper
:
self
.
_wrapped_base_type
=
base_type
.
wrapped_base_type
()
return
self
.
_wrapped_base_type
# if no wrapped base was found, this type is the oldest wrapped base
self
.
_wrapped_base_type
=
self
return
self
# iterate over the direct bases that support wrapping
def
iter_wrapped_base_types
(
self
):
for
base_type
in
self
.
base_classes
:
...
...
@@ -4252,11 +4237,10 @@ class CypClassType(CppClassType):
def
create_from_py_utility_code
(
self
,
env
):
if
not
self
.
wrapper_type
:
return
False
wrapper_objstruct
=
self
.
wrapped_base_type
().
wrapper_type
.
objstruct_cname
underlying_type_name
=
self
.
cname
self
.
from_py_function
=
"__Pyx_PyObject_AsCyObject<%s
, %s>"
%
(
wrapper_objstruct
,
underlying_type_name
)
self
.
from_py_function
=
"__Pyx_PyObject_AsCyObject<%s
>"
%
underlying_type_name
return
True
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
=
None
,
error_condition
=
None
):
extra_args
=
[
self
.
wrapper_type
.
typeptr_cname
if
self
.
wrapper_type
else
None
]
...
...
@@ -4265,7 +4249,7 @@ class CypClassType(CppClassType):
return
self
.
_assign_from_py_code
(
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
,
error_condition
,
extra_args
=
extra_args
)
def
empty_declaration_code
(
self
):
if
self
.
_empty_declaration
is
None
:
self
.
_empty_declaration
=
self
.
declaration_code
(
''
,
deref
=
1
)
...
...
Cython/Utility/CyObjects.cpp
View file @
4516a118
...
...
@@ -75,6 +75,19 @@
int
CyObject_TRYWLOCK
();
};
/*
* A POD type that has a compatible memory layout with any wrapper for a cypclass.
*
* Serves as a:
* - convenience type to cast a wrapper and access its underlying cyobject pointer.
* - reference for the memory layout that all cypclass wrappers must respect.
*/
struct
CyPyObject
{
PyObject_HEAD
CyObject
*
nogil_cyobject
;
};
/* All this is made available by member injection inside the module scope */
struct
ActhonResultInterface
:
public
CyObject
{
...
...
@@ -200,10 +213,9 @@
* - return NULL
*
* template:
* - W: the type of the extension type wrapper
* - U: the type of the underlying cypclass
*/
template
<
typename
W
,
typename
U
>
template
<
typename
U
>
static
inline
U
*
__Pyx_PyObject_AsCyObject
(
PyObject
*
ob
,
PyTypeObject
*
type
)
{
// the PyObject is not of the expected type
if
(
ob
->
ob_type
!=
type
)
{
...
...
@@ -211,7 +223,7 @@
return
NULL
;
}
W
*
wrapper
=
(
W
*
)
ob
;
CyPyObject
*
wrapper
=
(
CyPyObject
*
)
ob
;
U
*
underlying
=
dynamic_cast
<
U
*>
(
wrapper
->
nogil_cyobject
);
// no underlying cyobject: shouldn't happen, playing it safe for now
...
...
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