mirror of https://github.com/python/cpython
bpo-31443: Formulate the type slot initialization rules in terms of C99. (#3688)
This commit is contained in:
parent
5e02c7826f
commit
ca72589bfa
|
@ -177,16 +177,9 @@ the module. We'll expand this example later to have more interesting behavior.
|
||||||
For now, all we want to be able to do is to create new :class:`Noddy` objects.
|
For now, all we want to be able to do is to create new :class:`Noddy` objects.
|
||||||
To enable object creation, we have to provide a :c:member:`~PyTypeObject.tp_new` implementation.
|
To enable object creation, we have to provide a :c:member:`~PyTypeObject.tp_new` implementation.
|
||||||
In this case, we can just use the default implementation provided by the API
|
In this case, we can just use the default implementation provided by the API
|
||||||
function :c:func:`PyType_GenericNew`. We'd like to just assign this to the
|
function :c:func:`PyType_GenericNew`. ::
|
||||||
:c:member:`~PyTypeObject.tp_new` slot, but we can't, for portability sake, On some platforms or
|
|
||||||
compilers, we can't statically initialize a structure member with a function
|
|
||||||
defined in another C module, so, instead, we'll assign the :c:member:`~PyTypeObject.tp_new` slot
|
|
||||||
in the module initialization function just before calling
|
|
||||||
:c:func:`PyType_Ready`::
|
|
||||||
|
|
||||||
noddy_NoddyType.tp_new = PyType_GenericNew;
|
PyType_GenericNew, /* tp_new */
|
||||||
if (PyType_Ready(&noddy_NoddyType) < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
All the other type methods are *NULL*, so we'll go over them later --- that's
|
All the other type methods are *NULL*, so we'll go over them later --- that's
|
||||||
for a later section!
|
for a later section!
|
||||||
|
|
|
@ -308,7 +308,7 @@ static PyTypeObject Null_Type = {
|
||||||
0, /*tp_dictoffset*/
|
0, /*tp_dictoffset*/
|
||||||
0, /*tp_init*/
|
0, /*tp_init*/
|
||||||
0, /*tp_alloc*/
|
0, /*tp_alloc*/
|
||||||
0, /* see PyInit_xx */ /*tp_new*/
|
PyType_GenericNew, /*tp_new*/
|
||||||
0, /*tp_free*/
|
0, /*tp_free*/
|
||||||
0, /*tp_is_gc*/
|
0, /*tp_is_gc*/
|
||||||
};
|
};
|
||||||
|
@ -338,11 +338,19 @@ PyDoc_STRVAR(module_doc,
|
||||||
static int
|
static int
|
||||||
xx_exec(PyObject *m)
|
xx_exec(PyObject *m)
|
||||||
{
|
{
|
||||||
/* Due to cross platform compiler issues the slots must be filled
|
/* Slot initialization is subject to the rules of initializing globals.
|
||||||
* here. It's required for portability to Windows without requiring
|
C99 requires the initializers to be "address constants". Function
|
||||||
* C++. */
|
designators like 'PyType_GenericNew', with implicit conversion to
|
||||||
|
a pointer, are valid C99 address constants.
|
||||||
|
|
||||||
|
However, the unary '&' operator applied to a non-static variable
|
||||||
|
like 'PyBaseObject_Type' is not required to produce an address
|
||||||
|
constant. Compilers may support this (gcc does), MSVC does not.
|
||||||
|
|
||||||
|
Both compilers are strictly standard conforming in this particular
|
||||||
|
behavior.
|
||||||
|
*/
|
||||||
Null_Type.tp_base = &PyBaseObject_Type;
|
Null_Type.tp_base = &PyBaseObject_Type;
|
||||||
Null_Type.tp_new = PyType_GenericNew;
|
|
||||||
Str_Type.tp_base = &PyUnicode_Type;
|
Str_Type.tp_base = &PyUnicode_Type;
|
||||||
|
|
||||||
/* Finalize the type object including setting type of the new type
|
/* Finalize the type object including setting type of the new type
|
||||||
|
|
Loading…
Reference in New Issue