|
35 | 35 | /* See http://www.python.org/2.4/license for licensing details. */ |
36 | 36 |
|
37 | 37 | #include "Python.h" |
| 38 | +#include "moduleobject.h" // PyModuleDef_Slot |
38 | 39 | #include "structmember.h" // PyMemberDef |
39 | 40 |
|
| 41 | + |
40 | 42 | #define WINDOWS_LEAN_AND_MEAN |
41 | 43 | #include "windows.h" |
42 | 44 | #include <crtdbg.h> |
@@ -78,6 +80,17 @@ check_CancelIoEx() |
78 | 80 | return has_CancelIoEx; |
79 | 81 | } |
80 | 82 |
|
| 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 | +} |
81 | 94 |
|
82 | 95 | /* |
83 | 96 | * A Python object wrapping an OVERLAPPED structure and other useful data |
@@ -140,7 +153,9 @@ overlapped_dealloc(OverlappedObject *self) |
140 | 153 | if (self->write_buffer.obj) |
141 | 154 | PyBuffer_Release(&self->write_buffer); |
142 | 155 | Py_CLEAR(self->read_buffer); |
143 | | - PyObject_Del(self); |
| 156 | + PyTypeObject *tp = Py_TYPE(self); |
| 157 | + tp->tp_free(self); |
| 158 | + Py_DECREF(tp); |
144 | 159 | } |
145 | 160 |
|
146 | 161 | /*[clinic input] |
@@ -305,55 +320,29 @@ static PyMemberDef overlapped_members[] = { |
305 | 320 | {NULL} |
306 | 321 | }; |
307 | 322 |
|
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, |
347 | 336 | }; |
348 | 337 |
|
349 | 338 | static OverlappedObject * |
350 | | -new_overlapped(HANDLE handle) |
| 339 | +new_overlapped(PyObject *module, HANDLE handle) |
351 | 340 | { |
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); |
355 | 343 | if (!self) |
356 | 344 | return NULL; |
| 345 | + |
357 | 346 | self->handle = handle; |
358 | 347 | self->read_buffer = NULL; |
359 | 348 | self->pending = 0; |
@@ -409,7 +398,7 @@ _winapi_ConnectNamedPipe_impl(PyObject *module, HANDLE handle, |
409 | 398 | OverlappedObject *overlapped = NULL; |
410 | 399 |
|
411 | 400 | if (use_overlapped) { |
412 | | - overlapped = new_overlapped(handle); |
| 401 | + overlapped = new_overlapped(module, handle); |
413 | 402 | if (!overlapped) |
414 | 403 | return NULL; |
415 | 404 | } |
@@ -1527,7 +1516,7 @@ _winapi_ReadFile_impl(PyObject *module, HANDLE handle, DWORD size, |
1527 | 1516 | if (!buf) |
1528 | 1517 | return NULL; |
1529 | 1518 | if (use_overlapped) { |
1530 | | - overlapped = new_overlapped(handle); |
| 1519 | + overlapped = new_overlapped(module, handle); |
1531 | 1520 | if (!overlapped) { |
1532 | 1521 | Py_DECREF(buf); |
1533 | 1522 | return NULL; |
@@ -1810,7 +1799,7 @@ _winapi_WriteFile_impl(PyObject *module, HANDLE handle, PyObject *buffer, |
1810 | 1799 | OverlappedObject *overlapped = NULL; |
1811 | 1800 |
|
1812 | 1801 | if (use_overlapped) { |
1813 | | - overlapped = new_overlapped(handle); |
| 1802 | + overlapped = new_overlapped(module, handle); |
1814 | 1803 | if (!overlapped) |
1815 | 1804 | return NULL; |
1816 | 1805 | buf = &overlapped->write_buffer; |
@@ -1921,36 +1910,33 @@ static PyMethodDef winapi_functions[] = { |
1921 | 1910 | {NULL, NULL} |
1922 | 1911 | }; |
1923 | 1912 |
|
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 | | - |
1936 | 1913 | #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) |
1941 | 1927 | { |
1942 | | - PyObject *d; |
1943 | | - PyObject *m; |
| 1928 | + WinApiState *st = winapi_get_state(m); |
1944 | 1929 |
|
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 | + } |
1947 | 1934 |
|
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 | + } |
1952 | 1938 |
|
1953 | | - PyDict_SetItemString(d, "Overlapped", (PyObject *) &OverlappedType); |
| 1939 | + PyObject *d = PyModule_GetDict(m); |
1954 | 1940 |
|
1955 | 1941 | /* constants */ |
1956 | 1942 | WINAPI_CONSTANT(F_DWORD, CREATE_NEW_CONSOLE); |
@@ -2049,5 +2035,24 @@ PyInit__winapi(void) |
2049 | 2035 |
|
2050 | 2036 | WINAPI_CONSTANT("i", NULL); |
2051 | 2037 |
|
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); |
2053 | 2058 | } |
0 commit comments