[Python-checkins] bpo-1635741: Port _winapi ext to multi-stage init (GH-21371)

Mohamed Koubaa webhook-mailer at python.org
Thu Aug 13 10:23:19 EDT 2020


https://github.com/python/cpython/commit/e087f7cd43dfa4223c55a8ecd71f4a7d685178e4
commit: e087f7cd43dfa4223c55a8ecd71f4a7d685178e4
branch: master
author: Mohamed Koubaa <koubaa.m at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-08-13T16:22:48+02:00
summary:

bpo-1635741: Port _winapi ext to multi-stage init (GH-21371)

files:
A Misc/NEWS.d/next/Core and Builtins/2020-07-06-20-43-19.bpo-1635741.LYhsni.rst
M Modules/_winapi.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-07-06-20-43-19.bpo-1635741.LYhsni.rst b/Misc/NEWS.d/next/Core and Builtins/2020-07-06-20-43-19.bpo-1635741.LYhsni.rst
new file mode 100644
index 0000000000000..956fcd5d1ee29
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-07-06-20-43-19.bpo-1635741.LYhsni.rst	
@@ -0,0 +1 @@
+Port :mod:`winapi` to multiphase initialization
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index ddb11aa5a8204..7ba14095c96e1 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -35,8 +35,10 @@
 /* See http://www.python.org/2.4/license for licensing details. */
 
 #include "Python.h"
+#include "moduleobject.h"         // PyModuleDef_Slot
 #include "structmember.h"         // PyMemberDef
 
+
 #define WINDOWS_LEAN_AND_MEAN
 #include "windows.h"
 #include <crtdbg.h>
@@ -78,6 +80,17 @@ check_CancelIoEx()
     return has_CancelIoEx;
 }
 
+typedef struct {
+    PyTypeObject *overlapped_type;
+} WinApiState;
+
+static inline WinApiState*
+winapi_get_state(PyObject *module)
+{
+    void *state = PyModule_GetState(module);
+    assert(state != NULL);
+    return (WinApiState *)state;
+}
 
 /*
  * A Python object wrapping an OVERLAPPED structure and other useful data
@@ -140,7 +153,9 @@ overlapped_dealloc(OverlappedObject *self)
     if (self->write_buffer.obj)
         PyBuffer_Release(&self->write_buffer);
     Py_CLEAR(self->read_buffer);
-    PyObject_Del(self);
+    PyTypeObject *tp = Py_TYPE(self);
+    tp->tp_free(self);
+    Py_DECREF(tp);
 }
 
 /*[clinic input]
@@ -305,55 +320,29 @@ static PyMemberDef overlapped_members[] = {
     {NULL}
 };
 
-PyTypeObject OverlappedType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
-    /* tp_name           */ "_winapi.Overlapped",
-    /* tp_basicsize      */ sizeof(OverlappedObject),
-    /* tp_itemsize       */ 0,
-    /* tp_dealloc        */ (destructor) overlapped_dealloc,
-    /* tp_vectorcall_offset */ 0,
-    /* tp_getattr        */ 0,
-    /* tp_setattr        */ 0,
-    /* tp_as_async       */ 0,
-    /* tp_repr           */ 0,
-    /* tp_as_number      */ 0,
-    /* tp_as_sequence    */ 0,
-    /* tp_as_mapping     */ 0,
-    /* tp_hash           */ 0,
-    /* tp_call           */ 0,
-    /* tp_str            */ 0,
-    /* tp_getattro       */ 0,
-    /* tp_setattro       */ 0,
-    /* tp_as_buffer      */ 0,
-    /* tp_flags          */ Py_TPFLAGS_DEFAULT,
-    /* tp_doc            */ "OVERLAPPED structure wrapper",
-    /* tp_traverse       */ 0,
-    /* tp_clear          */ 0,
-    /* tp_richcompare    */ 0,
-    /* tp_weaklistoffset */ 0,
-    /* tp_iter           */ 0,
-    /* tp_iternext       */ 0,
-    /* tp_methods        */ overlapped_methods,
-    /* tp_members        */ overlapped_members,
-    /* tp_getset         */ 0,
-    /* tp_base           */ 0,
-    /* tp_dict           */ 0,
-    /* tp_descr_get      */ 0,
-    /* tp_descr_set      */ 0,
-    /* tp_dictoffset     */ 0,
-    /* tp_init           */ 0,
-    /* tp_alloc          */ 0,
-    /* tp_new            */ 0,
+static PyType_Slot winapi_overlapped_type_slots[] = {
+    {Py_tp_dealloc, overlapped_dealloc},
+    {Py_tp_doc, "OVERLAPPED structure wrapper"},
+    {Py_tp_methods, overlapped_methods},
+    {Py_tp_members, overlapped_members},
+    {0,0}
+};
+
+static PyType_Spec winapi_overlapped_type_spec = {
+    .name = "_winapi.Overlapped",
+    .basicsize = sizeof(OverlappedObject),
+    .flags = Py_TPFLAGS_DEFAULT,
+    .slots = winapi_overlapped_type_slots,
 };
 
 static OverlappedObject *
-new_overlapped(HANDLE handle)
+new_overlapped(PyObject *module, HANDLE handle)
 {
-    OverlappedObject *self;
-
-    self = PyObject_New(OverlappedObject, &OverlappedType);
+    WinApiState *st = winapi_get_state(module);
+    OverlappedObject *self = PyObject_New(OverlappedObject, st->overlapped_type);
     if (!self)
         return NULL;
+
     self->handle = handle;
     self->read_buffer = NULL;
     self->pending = 0;
@@ -409,7 +398,7 @@ _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
     OverlappedObject *overlapped = NULL;
 
     if (use_overlapped) {
-        overlapped = new_overlapped(handle);
+        overlapped = new_overlapped(module, handle);
         if (!overlapped)
             return NULL;
     }
@@ -1527,7 +1516,7 @@ _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size,
     if (!buf)
         return NULL;
     if (use_overlapped) {
-        overlapped = new_overlapped(handle);
+        overlapped = new_overlapped(module, handle);
         if (!overlapped) {
             Py_DECREF(buf);
             return NULL;
@@ -1810,7 +1799,7 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
     OverlappedObject *overlapped = NULL;
 
     if (use_overlapped) {
-        overlapped = new_overlapped(handle);
+        overlapped = new_overlapped(module, handle);
         if (!overlapped)
             return NULL;
         buf = &overlapped->write_buffer;
@@ -1921,36 +1910,33 @@ static PyMethodDef winapi_functions[] = {
     {NULL, NULL}
 };
 
-static struct PyModuleDef winapi_module = {
-    PyModuleDef_HEAD_INIT,
-    "_winapi",
-    NULL,
-    -1,
-    winapi_functions,
-    NULL,
-    NULL,
-    NULL,
-    NULL
-};
-
 #define WINAPI_CONSTANT(fmt, con) \
-    PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
-
-PyMODINIT_FUNC
-PyInit__winapi(void)
+    do { \
+        PyObject *value = Py_BuildValue(fmt, con); \
+        if (value == NULL) { \
+            return -1; \
+        } \
+        if (PyDict_SetItemString(d, #con, value) < 0) { \
+            Py_DECREF(value); \
+            return -1; \
+        } \
+        Py_DECREF(value); \
+    } while (0)
+
+static int winapi_exec(PyObject *m)
 {
-    PyObject *d;
-    PyObject *m;
+    WinApiState *st = winapi_get_state(m);
 
-    if (PyType_Ready(&OverlappedType) < 0)
-        return NULL;
+    st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &winapi_overlapped_type_spec, NULL);
+    if (st->overlapped_type == NULL) {
+        return -1;
+    }
 
-    m = PyModule_Create(&winapi_module);
-    if (m == NULL)
-        return NULL;
-    d = PyModule_GetDict(m);
+    if (PyModule_AddType(m, st->overlapped_type) < 0) {
+        return -1;
+    }
 
-    PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
+    PyObject *d = PyModule_GetDict(m);
 
     /* constants */
     WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
@@ -2049,5 +2035,24 @@ PyInit__winapi(void)
 
     WINAPI_CONSTANT("i", NULL);
 
-    return m;
+    return 0;
+}
+
+static PyModuleDef_Slot winapi_slots[] = {
+    {Py_mod_exec, winapi_exec},
+    {0, NULL}
+};
+
+static struct PyModuleDef winapi_module = {
+    PyModuleDef_HEAD_INIT,
+    .m_name = "_winapi",
+    .m_size = sizeof(WinApiState),
+    .m_methods = winapi_functions,
+    .m_slots = winapi_slots,
+};
+
+PyMODINIT_FUNC
+PyInit__winapi(void)
+{
+    return PyModuleDef_Init(&winapi_module);
 }



More information about the Python-checkins mailing list