bpo-34626: Document creating heap types from the C-API (GH-9154)
authorPetr Viktorin <encukou@gmail.com>
Fri, 24 May 2019 09:19:42 +0000 (11:19 +0200)
committerGitHub <noreply@github.com>
Fri, 24 May 2019 09:19:42 +0000 (11:19 +0200)
bpo-34626: Document creating heap types from the C-API

Add missing descriptions of PEP384's PyType_Spec and PyType_Slot,
along with some introductory prose.

Doc/c-api/type.rst
Doc/c-api/typeobj.rst

index 2474df2c90baad737cd4fc31f4f22808d194585b..8f8367ab77c8c4f9a5c7a41da33c9ab1406ccf80 100644 (file)
@@ -95,18 +95,6 @@ Type Objects
    from a type's base class.  Return ``0`` on success, or return ``-1`` and sets an
    exception on error.
 
-.. c:function:: PyObject* PyType_FromSpec(PyType_Spec *spec)
-
-   Creates and returns a heap type object from the *spec* passed to the function.
-
-.. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
-
-   Creates and returns a heap type object from the *spec*. In addition to that,
-   the created heap type contains all types contained by the *bases* tuple as base
-   types. This allows the caller to reference other heap types as base types.
-
-   .. versionadded:: 3.3
-
 .. c:function:: void* PyType_GetSlot(PyTypeObject *type, int slot)
 
    Return the function pointer stored in the given slot. If the
@@ -115,4 +103,107 @@ Type Objects
    Callers will typically cast the result pointer into the appropriate
    function type.
 
+   See :c:member:`PyType_Slot.slot` for possible values of the *slot* argument.
+
+   An exception is raised if *type* is not a heap type.
+
    .. versionadded:: 3.4
+
+
+Creating Heap-Allocated Types
+.............................
+
+The following functions and structs are used to create
+:ref:`heap types <heap-types>`.
+
+.. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
+
+   Creates and returns a heap type object from the *spec*.
+
+   If *bases* is a tuple, the created heap type contains all types contained
+   in it as base types.
+
+   If *bases* is *NULL*, the *Py_tp_base* slot is used instead.
+   If that also is *NULL*, the new type derives from :class:`object`.
+
+   This function calls :c:func:`PyType_Ready` on the new type.
+
+   .. versionadded:: 3.3
+
+.. c:function:: PyObject* PyType_FromSpec(PyType_Spec *spec)
+
+   Equivalent to ``PyType_FromSpecWithBases(spec, NULL)``.
+
+.. c:type:: PyType_Spec
+
+   Structure defining a type's behavior.
+
+   .. c:member:: const char* PyType_Spec.name
+
+      Name of the type, used to set :c:member:`PyTypeObject.tp_name`.
+
+   .. c:member:: const char* PyType_Spec.doc
+
+      Type docstring, used to set :c:member:`PyTypeObject.tp_doc`.
+
+   .. c:member:: int PyType_Spec.basicsize
+   .. c:member:: int PyType_Spec.itemsize
+
+      Size of the instance in bytes, used to set
+      :c:member:`PyTypeObject.tp_basicsize` and
+      :c:member:`PyTypeObject.tp_itemsize`.
+
+   .. c:member:: int PyType_Spec.flags
+
+      Type flags, used to set :c:member:`PyTypeObject.tp_flags`.
+
+      If the ``Py_TPFLAGS_HEAPTYPE`` flag is not set,
+      :c:func:`PyType_FromSpecWithBases` sets it automatically.
+
+   .. c:member:: PyType_Slot *PyType_Spec.slots
+
+      Array of :c:type:`PyType_Slot` structures.
+      Terminated by the special slot value ``{0, NULL}``.
+
+.. c:type:: PyType_Slot
+
+   Structure defining optional functionality of a type, containing a slot ID
+   and a value pointer.
+
+   .. c:member:: int PyType_Slot.slot
+
+      A slot ID.
+
+      Slot IDs are named like the field names of the structures
+      :c:type:`PyTypeObject`, :c:type:`PyNumberMethods`,
+      :c:type:`PySequenceMethods`, :c:type:`PyMappingMethods` and
+      :c:type:`PyAsyncMethods` with an added ``Py_`` prefix.
+      For example, use:
+
+      * ``Py_tp_dealloc`` to set :c:member:`PyTypeObject.tp_dealloc`
+      * ``Py_nb_add`` to set :c:member:`PyNumberMethods.nb_add`
+      * ``Py_sq_length`` to set :c:member:`PySequenceMethods.sq_length`
+
+      The following fields cannot be set using *PyType_Spec* and *PyType_Slot*:
+
+      * :c:member:`~PyTypeObject.tp_dict`
+      * :c:member:`~PyTypeObject.tp_mro`
+      * :c:member:`~PyTypeObject.tp_cache`
+      * :c:member:`~PyTypeObject.tp_subclasses`
+      * :c:member:`~PyTypeObject.tp_weaklist`
+      * :c:member:`~PyTypeObject.tp_print`
+      * :c:member:`~PyTypeObject.tp_weaklistoffset`
+      * :c:member:`~PyTypeObject.tp_dictoffset`
+      * :c:member:`~PyBufferProcs.bf_getbuffer`
+      * :c:member:`~PyBufferProcs.bf_releasebuffer`
+
+      Setting :c:data:`Py_tp_bases` may be problematic on some platforms.
+      To avoid issues, use the *bases* argument of
+      :py:func:`PyType_FromSpecWithBases` instead.
+
+   .. c:member:: void *PyType_Slot.pfunc
+
+      The desired value of the slot. In most cases, this is a pointer
+      to a function.
+
+      May not be *NULL*.
index b1d96db7f53df0e40cb0c87c0dcd771d062f8393..e0ea9b9b5f966375392e260f6434af9691aca2ef 100644 (file)
@@ -1822,16 +1822,35 @@ objects on the thread which called tp_dealloc will not violate any assumptions
 of the library.
 
 
+.. _heap-types:
+
 Heap Types
 ----------
 
-In addition to defining Python types statically, you can define them
-dynamically (i.e. to the heap) using  :c:func:`PyType_FromSpec` and
-:c:func:`PyType_FromSpecWithBases`.
+Traditionally, types defined in C code are *static*, that is,
+a static :c:type:`PyTypeObject` structure is defined directly in code
+and initialized using :c:func:`PyType_Ready`.
+
+This results in types that are limited relative to types defined in Python:
 
-.. XXX Explain how to use PyType_FromSpec().
+* Static types are limited to one base, i.e. they cannot use multiple
+  inheritance.
+* Static type objects (but not necessarily their instances) are immutable.
+  It is not possible to add or modify the type object's attributes from Python.
+* Static type objects are shared across
+  :ref:`sub-interpreters <sub-interpreter-support>`, so they should not
+  include any subinterpreter-specific state.
 
-.. XXX Document PyType_Spec.
+Also, since *PyTypeObject* is not part of the :ref:`stable ABI <stable>`,
+any extension modules using static types must be compiled for a specific
+Python minor version.
+
+An alternative to static types is *heap-allocated types*, or *heap types*
+for short, which correspond closely to classes created by Python's
+``class`` statement.
+
+This is done by filling a :c:type:`PyType_Spec` structure and calling
+:c:func:`PyType_FromSpecWithBases`.
 
 
 .. _number-structs: