summaryrefslogtreecommitdiffstats
path: root/Include/cpython
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-04-07 22:38:15 (GMT)
committerGitHub <noreply@github.com>2020-04-07 22:38:15 (GMT)
commit9205520d8c43488696d66cbdd9aefbb21871c508 (patch)
tree6c6d03828fddd763f261d89a9afef18b109c0d3d /Include/cpython
parentf9dd51e7db27d04e0b716d41a2804d5acbf145d1 (diff)
downloadcpython-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.h50
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().