Skip to content

Commit e087f7c

Browse files
authored
bpo-1635741: Port _winapi ext to multi-stage init (GH-21371)
1 parent c51db0e commit e087f7c

File tree

2 files changed

+79
-73
lines changed

2 files changed

+79
-73
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Port :mod:`winapi` to multiphase initialization

Modules/_winapi.c

Lines changed: 78 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@
3535
/* See http://www.python.org/2.4/license for licensing details. */
3636

3737
#include "Python.h"
38+
#include "moduleobject.h" // PyModuleDef_Slot
3839
#include "structmember.h" // PyMemberDef
3940

41+
4042
#define WINDOWS_LEAN_AND_MEAN
4143
#include "windows.h"
4244
#include <crtdbg.h>
@@ -78,6 +80,17 @@ check_CancelIoEx()
7880
return has_CancelIoEx;
7981
}
8082

83+
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+
}
8194

8295
/*
8396
* A Python object wrapping an OVERLAPPED structure and other useful data
@@ -140,7 +153,9 @@ overlapped_dealloc(OverlappedObject *self)
140153
if (self->write_buffer.obj)
141154
PyBuffer_Release(&self->write_buffer);
142155
Py_CLEAR(self->read_buffer);
143-
PyObject_Del(self);
156+
PyTypeObject *tp = Py_TYPE(self);
157+
tp->tp_free(self);
158+
Py_DECREF(tp);
144159
}
145160

146161
/*[clinic input]
@@ -305,55 +320,29 @@ static PyMemberDef overlapped_members[] = {
305320
{NULL}
306321
};
307322

308-
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
};
348337

349338
static 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);
355343
if (!self)
356344
return NULL;
345+
357346
self->handle = handle;
358347
self->read_buffer = NULL;
359348
self->pending = 0;
@@ -409,7 +398,7 @@ _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
409398
OverlappedObject *overlapped = NULL;
410399

411400
if (use_overlapped) {
412-
overlapped = new_overlapped(handle);
401+
overlapped = new_overlapped(module, handle);
413402
if (!overlapped)
414403
return NULL;
415404
}
@@ -1527,7 +1516,7 @@ _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size,
15271516
if (!buf)
15281517
return NULL;
15291518
if (use_overlapped) {
1530-
overlapped = new_overlapped(handle);
1519+
overlapped = new_overlapped(module, handle);
15311520
if (!overlapped) {
15321521
Py_DECREF(buf);
15331522
return NULL;
@@ -1810,7 +1799,7 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
18101799
OverlappedObject *overlapped = NULL;
18111800

18121801
if (use_overlapped) {
1813-
overlapped = new_overlapped(handle);
1802+
overlapped = new_overlapped(module, handle);
18141803
if (!overlapped)
18151804
return NULL;
18161805
buf = &overlapped->write_buffer;
@@ -1921,36 +1910,33 @@ static PyMethodDef winapi_functions[] = {
19211910
{NULL, NULL}
19221911
};
19231912

1924-
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);
19441929

1945-
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+
}
19471934

1948-
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+
}
19521938

1953-
PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType);
1939+
PyObject *d = PyModule_GetDict(m);
19541940

19551941
/* constants */
19561942
WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
@@ -2049,5 +2035,24 @@ PyInit__winapi(void)
20492035

20502036
WINAPI_CONSTANT("i", NULL);
20512037

2052-
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
}

0 commit comments

Comments
 (0)