Skip to content

Commit d3b5c48

Browse files
picnixzencukou
andauthored
Update Doc/extending/newtypes_tutorial.rst
Co-authored-by: Petr Viktorin <encukou@gmail.com>
1 parent 816c013 commit d3b5c48

1 file changed

Lines changed: 22 additions & 2 deletions

File tree

Doc/extending/newtypes_tutorial.rst

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,28 @@ be an instance of a subclass.
273273
.. note::
274274
The explicit cast to ``CustomObject *`` above is needed because we defined
275275
``Custom_dealloc`` to take a ``PyObject *`` argument, as the ``tp_dealloc``
276-
function pointer expects to receive a ``PyObject *`` argument. Otherwise,
277-
this would result in an undefined behaviour at runtime!
276+
function pointer expects to receive a ``PyObject *`` argument.
277+
By assigning to the the ``tp_dealloc`` slot of a type, we declare
278+
that it can only be called with instances of our ``CustomObject``
279+
class, so the cast to ``(CustomObject *)`` is safe.
280+
This is object-oriented polymorphism, in C!
281+
282+
In existing code, or in previous versions of this tutorial,
283+
you might see similar functions take a pointer to the subtype
284+
object structure (``CustomObject*``) directly, like this::
285+
286+
Custom_dealloc(CustomObject *self)
287+
{
288+
Py_XDECREF(self->first);
289+
Py_XDECREF(self->last);
290+
Py_TYPE(self)->tp_free((PyObject *) self);
291+
}
292+
...
293+
.tp_dealloc = (destructor) Custom_dealloc,
294+
295+
This does the same thing on all architectures that CPython
296+
supports, but according to the C standard, it invokes
297+
undefined behavior.
278298

279299
We want to make sure that the first and last names are initialized to empty
280300
strings, so we provide a ``tp_new`` implementation::

0 commit comments

Comments
 (0)