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. */
#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))
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
PyInit__winapi(void)
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);
}