]> granicus.if.org Git - python/commitdiff
bpo-31443: Formulate the type slot initialization rules in terms of C99. (#3688)
authorStefan Krah <skrah@bytereef.org>
Fri, 22 Sep 2017 15:44:58 +0000 (17:44 +0200)
committerGitHub <noreply@github.com>
Fri, 22 Sep 2017 15:44:58 +0000 (17:44 +0200)
Doc/extending/newtypes.rst
Modules/xxmodule.c

index f0e8985c61563dca156767ae3b91990d854d07da..0e36ba0aec07ae1c2d6c05c46425797ff12bb709 100644 (file)
@@ -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.
 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
-function :c:func:`PyType_GenericNew`.  We'd like to just assign this to the
-: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;
-   if (PyType_Ready(&noddy_NoddyType) < 0)
-       return;
+function :c:func:`PyType_GenericNew`. ::
+
+   PyType_GenericNew,         /* tp_new */
 
 All the other type methods are *NULL*, so we'll go over them later --- that's
 for a later section!
index 076440703f5f71cefb4ab948131dbf1508fe7b5a..c0564ea9674eac85f0bba40ce0e26ae65987fc2a 100644 (file)
@@ -308,7 +308,7 @@ static PyTypeObject Null_Type = {
     0,                          /*tp_dictoffset*/
     0,                          /*tp_init*/
     0,                          /*tp_alloc*/
-    0, /* see PyInit_xx */      /*tp_new*/
+    PyType_GenericNew,          /*tp_new*/
     0,                          /*tp_free*/
     0,                          /*tp_is_gc*/
 };
@@ -338,11 +338,19 @@ PyDoc_STRVAR(module_doc,
 static int
 xx_exec(PyObject *m)
 {
-    /* Due to cross platform compiler issues the slots must be filled
-     * here. It's required for portability to Windows without requiring
-     * C++. */
+    /* Slot initialization is subject to the rules of initializing globals.
+       C99 requires the initializers to be "address constants".  Function
+       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_new = PyType_GenericNew;
     Str_Type.tp_base = &PyUnicode_Type;
 
     /* Finalize the type object including setting type of the new type