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

This commit is contained in:
Mohamed Koubaa 2020-08-13 09:22:48 -05:00 committed by GitHub
parent c51db0ea40
commit e087f7cd43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 72 deletions

View File

@ -0,0 +1 @@
Port :mod:`winapi` to multiphase initialization

View File

@ -35,8 +35,10 @@
/* See http://www.python.org/2.4/license for licensing details. */ /* See http://www.python.org/2.4/license for licensing details. */
#include "Python.h" #include "Python.h"
#include "moduleobject.h" // PyModuleDef_Slot
#include "structmember.h" // PyMemberDef #include "structmember.h" // PyMemberDef
#define WINDOWS_LEAN_AND_MEAN #define WINDOWS_LEAN_AND_MEAN
#include "windows.h" #include "windows.h"
#include <crtdbg.h> #include <crtdbg.h>
@ -78,6 +80,17 @@ check_CancelIoEx()
return has_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 * A Python object wrapping an OVERLAPPED structure and other useful data
@ -140,7 +153,9 @@ overlapped_dealloc(OverlappedObject *self)
if (self->write_buffer.obj) if (self->write_buffer.obj)
PyBuffer_Release(&self->write_buffer); PyBuffer_Release(&self->write_buffer);
Py_CLEAR(self->read_buffer); Py_CLEAR(self->read_buffer);
PyObject_Del(self); PyTypeObject *tp = Py_TYPE(self);
tp->tp_free(self);
Py_DECREF(tp);
} }
/*[clinic input] /*[clinic input]
@ -305,55 +320,29 @@ static PyMemberDef overlapped_members[] = {
{NULL} {NULL}
}; };
PyTypeObject OverlappedType = { static PyType_Slot winapi_overlapped_type_slots[] = {
PyVarObject_HEAD_INIT(NULL, 0) {Py_tp_dealloc, overlapped_dealloc},
/* tp_name */ "_winapi.Overlapped", {Py_tp_doc, "OVERLAPPED structure wrapper"},
/* tp_basicsize */ sizeof(OverlappedObject), {Py_tp_methods, overlapped_methods},
/* tp_itemsize */ 0, {Py_tp_members, overlapped_members},
/* tp_dealloc */ (destructor) overlapped_dealloc, {0,0}
/* tp_vectorcall_offset */ 0, };
/* tp_getattr */ 0,
/* tp_setattr */ 0, static PyType_Spec winapi_overlapped_type_spec = {
/* tp_as_async */ 0, .name = "_winapi.Overlapped",
/* tp_repr */ 0, .basicsize = sizeof(OverlappedObject),
/* tp_as_number */ 0, .flags = Py_TPFLAGS_DEFAULT,
/* tp_as_sequence */ 0, .slots = winapi_overlapped_type_slots,
/* 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 OverlappedObject * static OverlappedObject *
new_overlapped(HANDLE handle) new_overlapped(PyObject *module, HANDLE handle)
{ {
OverlappedObject *self; WinApiState *st = winapi_get_state(module);
OverlappedObject *self = PyObject_New(OverlappedObject, st->overlapped_type);
self = PyObject_New(OverlappedObject, &OverlappedType);
if (!self) if (!self)
return NULL; return NULL;
self->handle = handle; self->handle = handle;
self->read_buffer = NULL; self->read_buffer = NULL;
self->pending = 0; self->pending = 0;
@ -409,7 +398,7 @@ _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle,
OverlappedObject *overlapped = NULL; OverlappedObject *overlapped = NULL;
if (use_overlapped) { if (use_overlapped) {
overlapped = new_overlapped(handle); overlapped = new_overlapped(module, handle);
if (!overlapped) if (!overlapped)
return NULL; return NULL;
} }
@ -1527,7 +1516,7 @@ _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size,
if (!buf) if (!buf)
return NULL; return NULL;
if (use_overlapped) { if (use_overlapped) {
overlapped = new_overlapped(handle); overlapped = new_overlapped(module, handle);
if (!overlapped) { if (!overlapped) {
Py_DECREF(buf); Py_DECREF(buf);
return NULL; return NULL;
@ -1810,7 +1799,7 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer,
OverlappedObject *overlapped = NULL; OverlappedObject *overlapped = NULL;
if (use_overlapped) { if (use_overlapped) {
overlapped = new_overlapped(handle); overlapped = new_overlapped(module, handle);
if (!overlapped) if (!overlapped)
return NULL; return NULL;
buf = &overlapped->write_buffer; buf = &overlapped->write_buffer;
@ -1921,36 +1910,33 @@ static PyMethodDef winapi_functions[] = {
{NULL, NULL} {NULL, NULL}
}; };
static struct PyModuleDef winapi_module = {
PyModuleDef_HEAD_INIT,
"_winapi",
NULL,
-1,
winapi_functions,
NULL,
NULL,
NULL,
NULL
};
#define WINAPI_CONSTANT(fmt, con) \ #define WINAPI_CONSTANT(fmt, con) \
PyDict_SetItemString(d, #con, Py_BuildValue(fmt, con)) 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)
PyMODINIT_FUNC static int winapi_exec(PyObject *m)
PyInit__winapi(void)
{ {
PyObject *d; WinApiState *st = winapi_get_state(m);
PyObject *m;
if (PyType_Ready(&OverlappedType) < 0) st->overlapped_type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &winapi_overlapped_type_spec, NULL);
return NULL; if (st->overlapped_type == NULL) {
return -1;
}
m = PyModule_Create(&winapi_module); if (PyModule_AddType(m, st->overlapped_type) < 0) {
if (m == NULL) return -1;
return NULL; }
d = PyModule_GetDict(m);
PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType); PyObject *d = PyModule_GetDict(m);
/* constants */ /* constants */
WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE); WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);
@ -2049,5 +2035,24 @@ PyInit__winapi(void)
WINAPI_CONSTANT("i", NULL); 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);
} }