mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	gh-129675: Update documentation for tp_basicsize & tp_itemsize (#129850)
* Update documentation for tp_basicsize & tp_itemsize - Add alignment requirement - Mention that ob_size is unreliable if you don't control it - Add some links for context - basicsize should include the base type in generaly not just PyObject This adds a “by-the-way” link to `PyObject_New`, which shouldn't be used for GC types. In order to be comfortable linking to it, I also add a link to `PyObject_GC_New` from its docs. And the same for `*Var` variants, while I'm here. * Strongly suggest Py_SIZE & Py_SET_SIZE
This commit is contained in:
		
							parent
							
								
									faadb446d9
								
							
						
					
					
						commit
						ad0f618ab3
					
				
					 3 changed files with 81 additions and 28 deletions
				
			
		| 
						 | 
					@ -35,6 +35,10 @@ Allocating Objects on the Heap
 | 
				
			||||||
   The size of the memory allocation is determined from the
 | 
					   The size of the memory allocation is determined from the
 | 
				
			||||||
   :c:member:`~PyTypeObject.tp_basicsize` field of the type object.
 | 
					   :c:member:`~PyTypeObject.tp_basicsize` field of the type object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Note that this function is unsuitable if *typeobj* has
 | 
				
			||||||
 | 
					   :c:macro:`Py_TPFLAGS_HAVE_GC` set. For such objects,
 | 
				
			||||||
 | 
					   use :c:func:`PyObject_GC_New` instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. c:macro:: PyObject_NewVar(TYPE, typeobj, size)
 | 
					.. c:macro:: PyObject_NewVar(TYPE, typeobj, size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +53,10 @@ Allocating Objects on the Heap
 | 
				
			||||||
   fields into the same allocation decreases the number of allocations,
 | 
					   fields into the same allocation decreases the number of allocations,
 | 
				
			||||||
   improving the memory management efficiency.
 | 
					   improving the memory management efficiency.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Note that this function is unsuitable if *typeobj* has
 | 
				
			||||||
 | 
					   :c:macro:`Py_TPFLAGS_HAVE_GC` set. For such objects,
 | 
				
			||||||
 | 
					   use :c:func:`PyObject_GC_NewVar` instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. c:function:: void PyObject_Del(void *op)
 | 
					.. c:function:: void PyObject_Del(void *op)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -456,6 +456,9 @@ The following functions and structs are used to create
 | 
				
			||||||
      class need *in addition* to the superclass.
 | 
					      class need *in addition* to the superclass.
 | 
				
			||||||
      Use :c:func:`PyObject_GetTypeData` to get a pointer to subclass-specific
 | 
					      Use :c:func:`PyObject_GetTypeData` to get a pointer to subclass-specific
 | 
				
			||||||
      memory reserved this way.
 | 
					      memory reserved this way.
 | 
				
			||||||
 | 
					      For negative :c:member:`!basicsize`, Python will insert padding when
 | 
				
			||||||
 | 
					      needed to meet :c:member:`~PyTypeObject.tp_basicsize`'s alignment
 | 
				
			||||||
 | 
					      requirements.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      .. versionchanged:: 3.12
 | 
					      .. versionchanged:: 3.12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -537,6 +537,9 @@ PyVarObject Slots
 | 
				
			||||||
   initialized to zero. For :ref:`dynamically allocated type objects
 | 
					   initialized to zero. For :ref:`dynamically allocated type objects
 | 
				
			||||||
   <heap-types>`, this field has a special internal meaning.
 | 
					   <heap-types>`, this field has a special internal meaning.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   This field should be accessed using the :c:func:`Py_SIZE()` and
 | 
				
			||||||
 | 
					   :c:func:`Py_SET_SIZE()` macros.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   **Inheritance:**
 | 
					   **Inheritance:**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   This field is not inherited by subtypes.
 | 
					   This field is not inherited by subtypes.
 | 
				
			||||||
| 
						 | 
					@ -592,42 +595,81 @@ and :c:data:`PyType_Type` effectively act as defaults.)
 | 
				
			||||||
   These fields allow calculating the size in bytes of instances of the type.
 | 
					   These fields allow calculating the size in bytes of instances of the type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   There are two kinds of types: types with fixed-length instances have a zero
 | 
					   There are two kinds of types: types with fixed-length instances have a zero
 | 
				
			||||||
   :c:member:`~PyTypeObject.tp_itemsize` field, types with variable-length instances have a non-zero
 | 
					   :c:member:`!tp_itemsize` field, types with variable-length instances have a non-zero
 | 
				
			||||||
   :c:member:`~PyTypeObject.tp_itemsize` field.  For a type with fixed-length instances, all
 | 
					   :c:member:`!tp_itemsize` field.  For a type with fixed-length instances, all
 | 
				
			||||||
   instances have the same size, given in :c:member:`~PyTypeObject.tp_basicsize`.
 | 
					   instances have the same size, given in :c:member:`!tp_basicsize`.
 | 
				
			||||||
 | 
					   (Exceptions to this rule can be made using
 | 
				
			||||||
 | 
					   :c:func:`PyUnstable_Object_GC_NewWithExtraData`.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   For a type with variable-length instances, the instances must have an
 | 
					   For a type with variable-length instances, the instances must have an
 | 
				
			||||||
   :c:member:`~PyVarObject.ob_size` field, and the instance size is :c:member:`~PyTypeObject.tp_basicsize` plus N
 | 
					   :c:member:`~PyVarObject.ob_size` field, and the instance size is
 | 
				
			||||||
   times :c:member:`~PyTypeObject.tp_itemsize`, where N is the "length" of the object.  The value of
 | 
					   :c:member:`!tp_basicsize` plus N times :c:member:`!tp_itemsize`,
 | 
				
			||||||
   N is typically stored in the instance's :c:member:`~PyVarObject.ob_size` field.  There are
 | 
					   where N is the "length" of the object.
 | 
				
			||||||
   exceptions:  for example, ints use a negative :c:member:`~PyVarObject.ob_size` to indicate a
 | 
					 | 
				
			||||||
   negative number, and N is ``abs(ob_size)`` there.  Also, the presence of an
 | 
					 | 
				
			||||||
   :c:member:`~PyVarObject.ob_size` field in the instance layout doesn't mean that the instance
 | 
					 | 
				
			||||||
   structure is variable-length (for example, the structure for the list type has
 | 
					 | 
				
			||||||
   fixed-length instances, yet those instances have a meaningful :c:member:`~PyVarObject.ob_size`
 | 
					 | 
				
			||||||
   field).
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
   The basic size includes the fields in the instance declared by the macro
 | 
					   Functions like :c:func:`PyObject_NewVar` will take the value of N as an
 | 
				
			||||||
   :c:macro:`PyObject_HEAD` or :c:macro:`PyObject_VAR_HEAD` (whichever is used to
 | 
					   argument, and store in the instance's :c:member:`~PyVarObject.ob_size` field.
 | 
				
			||||||
   declare the instance struct) and this in turn includes the  :c:member:`~PyObject._ob_prev` and
 | 
					   Note that the :c:member:`~PyVarObject.ob_size` field may later be used for
 | 
				
			||||||
   :c:member:`~PyObject._ob_next` fields if they are present.  This means that the only correct
 | 
					   other purposes. For example, :py:type:`int` instances use the bits of
 | 
				
			||||||
   way to get an initializer for the :c:member:`~PyTypeObject.tp_basicsize` is to use the
 | 
					   :c:member:`~PyVarObject.ob_size` in an implementation-defined
 | 
				
			||||||
 | 
					   way; the underlying storage and its size should be acessed using
 | 
				
			||||||
 | 
					   :c:func:`PyLong_Export`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   .. note::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      The :c:member:`~PyVarObject.ob_size` field should be accessed using
 | 
				
			||||||
 | 
					      the :c:func:`Py_SIZE()` and :c:func:`Py_SET_SIZE()` macros.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Also, the presence of an :c:member:`~PyVarObject.ob_size` field in the
 | 
				
			||||||
 | 
					   instance layout doesn't mean that the instance structure is variable-length.
 | 
				
			||||||
 | 
					   For example, the :py:type:`list` type has fixed-length instances, yet those
 | 
				
			||||||
 | 
					   instances have a :c:member:`~PyVarObject.ob_size` field.
 | 
				
			||||||
 | 
					   (As with :py:type:`int`, avoid reading lists' :c:member:`!ob_size` directly.
 | 
				
			||||||
 | 
					   Call :c:func:`PyList_Size` instead.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   The :c:member:`!tp_basicsize` includes size needed for data of the type's
 | 
				
			||||||
 | 
					   :c:member:`~PyTypeObject.tp_base`, plus any extra data needed
 | 
				
			||||||
 | 
					   by each instance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   The  correct way to set :c:member:`!tp_basicsize` is to use the
 | 
				
			||||||
   ``sizeof`` operator on the struct used to declare the instance layout.
 | 
					   ``sizeof`` operator on the struct used to declare the instance layout.
 | 
				
			||||||
   The basic size does not include the GC header size.
 | 
					   This struct must include the struct used to declare the base type.
 | 
				
			||||||
 | 
					   In other words, :c:member:`!tp_basicsize` must be greater than or equal
 | 
				
			||||||
 | 
					   to the base's :c:member:`!tp_basicsize`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   A note about alignment: if the variable items require a particular alignment,
 | 
					   Since every type is a subtype of :py:type:`object`, this struct must
 | 
				
			||||||
   this should be taken care of by the value of :c:member:`~PyTypeObject.tp_basicsize`.  Example:
 | 
					   include :c:type:`PyObject` or :c:type:`PyVarObject` (depending on
 | 
				
			||||||
   suppose a type implements an array of ``double``. :c:member:`~PyTypeObject.tp_itemsize` is
 | 
					   whether :c:member:`~PyVarObject.ob_size` should be included). These are
 | 
				
			||||||
   ``sizeof(double)``. It is the programmer's responsibility that
 | 
					   usually defined by the macro :c:macro:`PyObject_HEAD` or
 | 
				
			||||||
   :c:member:`~PyTypeObject.tp_basicsize` is a multiple of ``sizeof(double)`` (assuming this is the
 | 
					   :c:macro:`PyObject_VAR_HEAD`, respectively.
 | 
				
			||||||
   alignment requirement for ``double``).
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
   For any type with variable-length instances, this field must not be ``NULL``.
 | 
					   The basic size does not include the GC header size, as that header is not
 | 
				
			||||||
 | 
					   part of :c:macro:`PyObject_HEAD`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   For cases where struct used to declare the base type is unknown,
 | 
				
			||||||
 | 
					   see :c:member:`PyType_Spec.basicsize` and :c:func:`PyType_FromMetaclass`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Notes about alignment:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   - :c:member:`!tp_basicsize` must be a multiple of ``_Alignof(PyObject)``.
 | 
				
			||||||
 | 
					     When using ``sizeof`` on a ``struct`` that includes
 | 
				
			||||||
 | 
					     :c:macro:`PyObject_HEAD`, as recommended, the compiler ensures this.
 | 
				
			||||||
 | 
					     When not using a C ``struct``, or when using compiler
 | 
				
			||||||
 | 
					     extensions like ``__attribute__((packed))``, it is up to you.
 | 
				
			||||||
 | 
					   - If the variable items require a particular alignment,
 | 
				
			||||||
 | 
					     :c:member:`!tp_basicsize` and :c:member:`!tp_itemsize` must each be a
 | 
				
			||||||
 | 
					     multiple of that alignment.
 | 
				
			||||||
 | 
					     For example, if a type's variable part stores a ``double``, it is
 | 
				
			||||||
 | 
					     your responsibility that both fields are a multiple of
 | 
				
			||||||
 | 
					     ``_Alignof(double)``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   **Inheritance:**
 | 
					   **Inheritance:**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   These fields are inherited separately by subtypes.  If the base type has a
 | 
					   These fields are inherited separately by subtypes.
 | 
				
			||||||
   non-zero :c:member:`~PyTypeObject.tp_itemsize`, it is generally not safe to set
 | 
					   (That is, if the field is set to zero, :c:func:`PyType_Ready` will copy
 | 
				
			||||||
 | 
					   the value from the base type, indicating that the instances do not
 | 
				
			||||||
 | 
					   need additional storage.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   If the base type has a non-zero :c:member:`~PyTypeObject.tp_itemsize`, it is generally not safe to set
 | 
				
			||||||
   :c:member:`~PyTypeObject.tp_itemsize` to a different non-zero value in a subtype (though this
 | 
					   :c:member:`~PyTypeObject.tp_itemsize` to a different non-zero value in a subtype (though this
 | 
				
			||||||
   depends on the implementation of the base type).
 | 
					   depends on the implementation of the base type).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue