bpo-1635741: Port _winapi ext to multi-stage init (GH-21371) · python/cpython@e087f7c
@@ -35,8 +35,10 @@
3535/* See http://www.python.org/2.4/license for licensing details. */
36363737#include "Python.h"
38+#include "moduleobject.h" // PyModuleDef_Slot
3839#include "structmember.h" // PyMemberDef
394041+4042#define WINDOWS_LEAN_AND_MEAN
4143#include "windows.h"
4244#include <crtdbg.h>
@@ -78,6 +80,17 @@ check_CancelIoEx()
7880return has_CancelIoEx;
7981}
808283+typedef struct {
84+PyTypeObject *overlapped_type;
85+} WinApiState;
86+87+static inline WinApiState*
88+winapi_get_state(PyObject *module)
89+{
90+void *state = PyModule_GetState(module);
91+assert(state != NULL);
92+return (WinApiState *)state;
93+}
81948295/*
8396 * A Python object wrapping an OVERLAPPED structure and other useful data
@@ -140,7 +153,9 @@ overlapped_dealloc(OverlappedObject *self)
140153if (self->write_buffer.obj)
141154PyBuffer_Release(&self->write_buffer);
142155Py_CLEAR(self->read_buffer);
143-PyObject_Del(self);
156+PyTypeObject *tp = Py_TYPE(self);
157+tp->tp_free(self);
158+Py_DECREF(tp);
144159}
145160146161/*[clinic input]
@@ -305,55 +320,29 @@ static PyMemberDef overlapped_members[] = {
305320 {NULL}
306321};
307322308-PyTypeObject OverlappedType = {
309-PyVarObject_HEAD_INIT(NULL, 0)
310-/* tp_name */ "_winapi.Overlapped",
311-/* tp_basicsize */ sizeof(OverlappedObject),
312-/* tp_itemsize */ 0,
313-/* tp_dealloc */ (destructor) overlapped_dealloc,
314-/* tp_vectorcall_offset */ 0,
315-/* tp_getattr */ 0,
316-/* tp_setattr */ 0,
317-/* tp_as_async */ 0,
318-/* tp_repr */ 0,
319-/* tp_as_number */ 0,
320-/* tp_as_sequence */ 0,
321-/* tp_as_mapping */ 0,
322-/* tp_hash */ 0,
323-/* tp_call */ 0,
324-/* tp_str */ 0,
325-/* tp_getattro */ 0,
326-/* tp_setattro */ 0,
327-/* tp_as_buffer */ 0,
328-/* tp_flags */ Py_TPFLAGS_DEFAULT,
329-/* tp_doc */ "OVERLAPPED structure wrapper",
330-/* tp_traverse */ 0,
331-/* tp_clear */ 0,
332-/* tp_richcompare */ 0,
333-/* tp_weaklistoffset */ 0,
334-/* tp_iter */ 0,
335-/* tp_iternext */ 0,
336-/* tp_methods */ overlapped_methods,
337-/* tp_members */ overlapped_members,
338-/* tp_getset */ 0,
339-/* tp_base */ 0,
340-/* tp_dict */ 0,
341-/* tp_descr_get */ 0,
342-/* tp_descr_set */ 0,
343-/* tp_dictoffset */ 0,
344-/* tp_init */ 0,
345-/* tp_alloc */ 0,
346-/* tp_new */ 0,
323+static PyType_Slot winapi_overlapped_type_slots[] = {
324+ {Py_tp_dealloc, overlapped_dealloc},
325+ {Py_tp_doc, "OVERLAPPED structure wrapper"},
326+ {Py_tp_methods, overlapped_methods},
327+ {Py_tp_members, overlapped_members},
328+ {0,0}
329+};
330+331+static PyType_Spec winapi_overlapped_type_spec = {
332+ .name = "_winapi.Overlapped",
333+ .basicsize = sizeof(OverlappedObject),
334+ .flags = Py_TPFLAGS_DEFAULT,
335+ .slots = winapi_overlapped_type_slots,
347336};
348337349338static OverlappedObject *
350-new_overlapped(HANDLE handle)
339+new_overlapped(PyObject *module, HANDLE handle)
351340{
352-OverlappedObject *self;
353-354-self = PyObject_New(OverlappedObject, &OverlappedType);
341+WinApiState *st = winapi_get_state(module);
342+OverlappedObject *self = PyObject_New(OverlappedObject, st->overlapped_type);
355343if (!self)
356344return NULL;
345+357346self->handle = handle;
358347self->read_buffer = NULL;
359348self->pending = 0;
@@ -409,7 +398,7 @@ _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
409398OverlappedObject *overlapped = NULL;
410399411400if (use_overlapped) {
412-overlapped = new_overlapped(handle);
401+overlapped = new_overlapped(module, handle);
413402if (!overlapped)
414403return NULL;
415404 }
@@ -1527,7 +1516,7 @@ _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size,
15271516if (!buf)
15281517return NULL;
15291518if (use_overlapped) {
1530-overlapped = new_overlapped(handle);
1519+overlapped = new_overlapped(module, handle);
15311520if (!overlapped) {
15321521Py_DECREF(buf);
15331522return NULL;
@@ -1810,7 +1799,7 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
18101799OverlappedObject *overlapped = NULL;
1811180018121801if (use_overlapped) {
1813-overlapped = new_overlapped(handle);
1802+overlapped = new_overlapped(module, handle);
18141803if (!overlapped)
18151804return NULL;
18161805buf = &overlapped->write_buffer;
@@ -1921,36 +1910,33 @@ static PyMethodDef winapi_functions[] = {
19211910 {NULL, NULL}
19221911};
192319121924-static struct PyModuleDef winapi_module = {
1925-PyModuleDef_HEAD_INIT,
1926-"_winapi",
1927-NULL,
1928--1,
1929-winapi_functions,
1930-NULL,
1931-NULL,
1932-NULL,
1933-NULL
1934-};
1935-19361913#define WINAPI_CONSTANT(fmt, con) \
1937- PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con))
1938-1939-PyMODINIT_FUNC
1940-PyInit__winapi(void)
1914+ do { \
1915+ PyObject *value = Py_BuildValue(fmt, con); \
1916+ if (value == NULL) { \
1917+ return -1; \
1918+ } \
1919+ if (PyDict_SetItemString(d, #con, value) < 0) { \
1920+ Py_DECREF(value); \
1921+ return -1; \
1922+ } \
1923+ Py_DECREF(value); \
1924+ } while (0)
1925+1926+static int winapi_exec(PyObject *m)
19411927{
1942-PyObject *d;
1943-PyObject *m;
1928+WinApiState *st = winapi_get_state(m);
194419291945-if (PyType_Ready(&OverlappedType) < 0)
1946-return NULL;
1930+st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &winapi_overlapped_type_spec, NULL);
1931+if (st->overlapped_type == NULL) {
1932+return -1;
1933+ }
194719341948-m = PyModule_Create(&winapi_module);
1949-if (m == NULL)
1950-return NULL;
1951-d = PyModule_GetDict(m);
1935+if (PyModule_AddType(m, st->overlapped_type) < 0) {
1936+return -1;
1937+ }
195219381953-PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1939+PyObject *d = PyModule_GetDict(m);
1954194019551941/* constants */
19561942WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
@@ -2049,5 +2035,24 @@ PyInit__winapi(void)
2049203520502036WINAPI_CONSTANT("i", NULL);
205120372052-return m;
2038+return 0;
2039+}
2040+2041+static PyModuleDef_Slot winapi_slots[] = {
2042+ {Py_mod_exec, winapi_exec},
2043+ {0, NULL}
2044+};
2045+2046+static struct PyModuleDef winapi_module = {
2047+PyModuleDef_HEAD_INIT,
2048+ .m_name = "_winapi",
2049+ .m_size = sizeof(WinApiState),
2050+ .m_methods = winapi_functions,
2051+ .m_slots = winapi_slots,
2052+};
2053+2054+PyMODINIT_FUNC
2055+PyInit__winapi(void)
2056+{
2057+return PyModuleDef_Init(&winapi_module);
20532058}