8000 PyTypeObject · mscherer/pythoncapi@53872b5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 53872b5

Browse files
committed
PyTypeObject
1 parent ad08248 commit 53872b5

File tree

3 files changed

+130
-0
lines changed

3 files changed

+130
-0
lines changed

doc/bad_api.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ Don't leak the structures like ``PyObject`` or ``PyTupleObject`` to not
121121
access directly fields, to not use fixed offset at the ABI level. Replace
122122
macros with functions calls. PyPy already does this in its C API (``cpyext``).
123123

124+
PyType_Ready() and setting directly PyTypeObject fields
125+
=======================================================
126+
127+
* ``PyTypeObject`` structure should become opaquet
128+
* ``PyType_Ready()`` should be removed
129+
130+
See :ref:`Implement a PyTypeObject in C <impl-pytype>` for the rationale.
131+
124132
Integer overflow
125133
================
126134

doc/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Pages
3636
new_api
3737
runtimes
3838
old_c_api
39+
type_object
3940
remove_functions
4041
optimization_ideas
4142
backward_compatibility

doc/type_object.rst

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
.. _impl-pytype:
2+
3+
+++++++++++++++++++++++++++++
4+
Implement a PyTypeObject in C
5+
+++++++++++++++++++++++++++++
6+
7+
Old C API
8+
=========
9+
10+
Truncated example of the ``PyUnicode_Type`` (Python ``str``)::
11+
12+
PyTypeObject PyUnicode_Type = {
13+
PyVarObject_HEAD_INIT(&PyType_Type, 0)
14+
"str", /* tp_name */
15+
sizeof(PyUnicodeObject), /* tp_basicsize */
16+
0, /* tp_itemsize */
17+
/* Slots */
18+
(destructor)unicode_dealloc, /* tp_dealloc */
19+
0, /* tp_print */
20+
0, /* tp_getattr */
21+
0, /* tp_setattr */
22+
0, /* tp_reserved */
23+
unicode_repr, /* tp_repr */
24+
&unicode_as_number, /* tp_as_number */
25+
&unicode_as_sequence, /* tp_as_sequence */
26+
&unicode_as_mapping, /* tp_as_mapping */
27+
(hashfunc) unicode_hash, /* tp_hash*/
28+
(...)
29+
0, /* tp_init */
30+
0, /* tp_alloc */
31+
unicode_new, /* tp_new */
32+
PyObject_Del, /* tp_free */
33+
};
34+
35+
The type must then be initialized once by calling ``PyType_Ready()``::
36+
37+
if (PyType_Ready(&PyUnicode_Type) < 0) { /* handle the error */ }
38+
39+
This API has an obvious flaw: it rely on the exact implementation of
40+
``PyTypeObject``, the developer has to know all fields.
41+
42+
Variant using C99 syntax::
43+
44+
static PyTypeObject _abc_data_type = {
45+
PyVarObject_HEAD_INIT(&PyType_Type, 0)
46+
"_abc_data", /*tp_name*/
47+
sizeof(_abc_data), /*tp_size*/
48+
.tp_dealloc = (destructor)abc_data_dealloc,
49+
.tp_flags = Py_TPFLAGS_DEFAULT,
50+
.tp_alloc = PyType_GenericAlloc,
51+
.tp_new = abc_data_new,
52+
};
53+
54+
PyType_FromSpec()
55+
=================
56+
57+
Python 3.1 introduced a new function::
58+
59+
PyObject* PyType_FromSpec(PyType_Spec *spec)
60+
61+
Documentation:
62+
63+
Creates and returns a heap type object from the *spec* passed to the function.
64+
65+
There are two additional **private** functions (excluded from the :ref:`Stable
66+
ABI <stable-abi>`)::
67+
68+
PyObject* PyType_FromSpecWithBases(PyType_Spec*, PyObject*);
69+
void* PyType_GetSlot(PyTypeObject*, int);
70+
71+
``PyType_GetSlot()`` expects a slot number which comes from
72+
`Include/typeslots.inc
73+
<https://github.com/python/cpython/blob/master/Include/typeslots.h>`_: see
74+
``slotoffsets`` array. The file contains the warning:
75+
76+
Do not renumber the file; these numbers are **part of the stable ABI**.
77+
78+
Some slots have been disabled (`bpo-10181
79+
<https://bugs.python.org/issue10181>`_)::
80+
81+
/* Disabled, see #10181 */
82+
#undef Py_bf_getbuffer
83+
#undef Py_bf_releasebuffer
84+
85+
Examples of slots::
86+
87+
#define Py_nb_add 7
88+
89+
#define Py_tp_alloc 47
90+
91+
#define Py_tp_call 50
92+
93+
#define Py_tp_clear 51
94+
95+
#define Py_tp_doc 56
96+
97+
#define Py_tp_getattr 57
98+
99+
Example of type::
100+
101+
static PyType_Slot PyCursesPanel_Type_slots[] = {
102+
{Py_tp_dealloc, PyCursesPanel_Dealloc},
103+
{Py_tp_methods, PyCursesPanel_Methods},
104+
{0, 0},
105+
};
106+
107+
static PyType_Spec PyCursesPanel_Type_spec = {
108+
"_curses_panel.panel",
109+
sizeof(PyCursesPanelObject),
110+
0,
111+
Py_TPFLAGS_DEFAULT,
112+
PyCursesPanel_Type_slots
113+
};
114+
115+
Later initialized by::
116+
117+
PyObject *v = PyType_FromSpec(&PyCursesPanel_Type_spec);
118+
if (v == NULL)
119+
goto fail;
120+
((PyTypeObject *)v)->tp_new = NULL;
121+
_curses_panelstate(m)->PyCursesPanel_Type = v;

0 commit comments

Comments
 (0)
0