diff options
author | Victor Stinner <vstinner@python.org> | 2020-04-07 22:38:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-07 22:38:15 (GMT) |
commit | 9205520d8c43488696d66cbdd9aefbb21871c508 (patch) | |
tree | 6c6d03828fddd763f261d89a9afef18b109c0d3d /Include/cpython | |
parent | f9dd51e7db27d04e0b716d41a2804d5acbf145d1 (diff) | |
download | cpython-9205520d8c43488696d66cbdd9aefbb21871c508.zip cpython-9205520d8c43488696d66cbdd9aefbb21871c508.tar.gz cpython-9205520d8c43488696d66cbdd9aefbb21871c508.tar.bz2 |
bpo-40170: PyObject_NEW() becomes an alias to PyObject_New() (GH-19379)
The PyObject_NEW() macro becomes an alias to the PyObject_New()
macro, and the PyObject_NEW_VAR() macro becomes an alias to the
PyObject_NewVar() macro, to hide implementation details. They no
longer access directly the PyTypeObject.tp_basicsize member.
Exclude _PyObject_SIZE() and _PyObject_VAR_SIZE() macros from
the limited C API.
Replace PyObject_NEW() with PyObject_New() and replace
PyObject_NEW_VAR() with PyObject_NewVar().
Diffstat (limited to 'Include/cpython')
-rw-r--r-- | Include/cpython/objimpl.h | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/Include/cpython/objimpl.h b/Include/cpython/objimpl.h index 2f802e9..832622c 100644 --- a/Include/cpython/objimpl.h +++ b/Include/cpython/objimpl.h @@ -6,6 +6,56 @@ extern "C" { #endif +#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize ) + +/* _PyObject_VAR_SIZE returns the number of bytes (as size_t) allocated for a + vrbl-size object with nitems items, exclusive of gc overhead (if any). The + value is rounded up to the closest multiple of sizeof(void *), in order to + ensure that pointer fields at the end of the object are correctly aligned + for the platform (this is of special importance for subclasses of, e.g., + str or int, so that pointers can be stored after the embedded data). + + Note that there's no memory wastage in doing this, as malloc has to + return (at worst) pointer-aligned memory anyway. +*/ +#if ((SIZEOF_VOID_P - 1) & SIZEOF_VOID_P) != 0 +# error "_PyObject_VAR_SIZE requires SIZEOF_VOID_P be a power of 2" +#endif + +#define _PyObject_VAR_SIZE(typeobj, nitems) \ + _Py_SIZE_ROUND_UP((typeobj)->tp_basicsize + \ + (nitems)*(typeobj)->tp_itemsize, \ + SIZEOF_VOID_P) + + +/* This example code implements an object constructor with a custom + allocator, where PyObject_New is inlined, and shows the important + distinction between two steps (at least): + 1) the actual allocation of the object storage; + 2) the initialization of the Python specific fields + in this storage with PyObject_{Init, InitVar}. + + PyObject * + YourObject_New(...) + { + PyObject *op; + + op = (PyObject *) Your_Allocator(_PyObject_SIZE(YourTypeStruct)); + if (op == NULL) + return PyErr_NoMemory(); + + PyObject_Init(op, &YourTypeStruct); + + op->ob_field = value; + ... + return op; + } + + Note that in C++, the use of the new operator usually implies that + the 1st step is performed automatically for you, so in a C++ class + constructor you would start directly with PyObject_Init/InitVar. */ + + /* Inline functions trading binary compatibility for speed: PyObject_INIT() is the fast version of PyObject_Init(), and PyObject_INIT_VAR() is the fast version of PyObject_InitVar(). |