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()

7880

return 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)

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

}

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

};

348337349338

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;

410399411400

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;

1811180018121801

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

};

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 */

19561942

WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE);

@@ -2049,5 +2035,24 @@ PyInit__winapi(void)

2049203520502036

WINAPI_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

}