|
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