winrt-runtime 2.0.1__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/PKG-INFO +2 -2
- winrt_runtime-2.2.0/_winrt.cpp +592 -0
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/_winrt_array.cpp +4 -26
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/pyproject.toml +4 -3
- winrt_runtime-2.2.0/pywinrt-version.txt +1 -0
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/runtime.cpp +136 -21
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/src/winrt/_winrt.pyi +8 -1
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/src/winrt/system/__init__.py +30 -0
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/src/winrt_runtime.egg-info/PKG-INFO +2 -2
- winrt_runtime-2.0.1/_winrt.cpp +0 -365
- winrt_runtime-2.0.1/pywinrt-version.txt +0 -1
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/README.md +0 -0
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/setup.cfg +0 -0
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/setup.py +0 -0
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/src/winrt/py.typed +0 -0
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/src/winrt_runtime.egg-info/SOURCES.txt +0 -0
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/src/winrt_runtime.egg-info/dependency_links.txt +0 -0
- {winrt_runtime-2.0.1 → winrt_runtime-2.2.0}/src/winrt_runtime.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: winrt-runtime
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python projection of Windows Runtime (WinRT) APIs
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Documentation, https://pywinrt.readthedocs.io
|
|
@@ -10,7 +10,7 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
|
-
Requires-Python: <3.
|
|
13
|
+
Requires-Python: <3.14,>=3.9
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
|
|
16
16
|
# winrt-runtime
|
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
// must be included before winrt to avoid compile errors
|
|
2
|
+
#include <Shobjidl.h>
|
|
3
|
+
#include <libloaderapi.h>
|
|
4
|
+
|
|
5
|
+
#define PYWINRT_RUNTIME_MODULE
|
|
6
|
+
#include "pybase.h"
|
|
7
|
+
#include "pyruntime.h"
|
|
8
|
+
#include <winrt/base.h>
|
|
9
|
+
|
|
10
|
+
namespace py::cpp::_winrt
|
|
11
|
+
{
|
|
12
|
+
// BEGIN: class _winrt.Object:
|
|
13
|
+
|
|
14
|
+
static constexpr const char* const type_name_Object = "Object";
|
|
15
|
+
|
|
16
|
+
PyDoc_STRVAR(Object_doc, "base class for wrapped WinRT object instances.");
|
|
17
|
+
|
|
18
|
+
static PyObject* Object_new(
|
|
19
|
+
PyTypeObject* /*unused*/, PyObject* /*unused*/, PyObject* /*unused*/) noexcept
|
|
20
|
+
{
|
|
21
|
+
py::set_invalid_activation_error(type_name_Object);
|
|
22
|
+
return nullptr;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static void Object_dealloc(
|
|
26
|
+
py::winrt_wrapper<winrt::Windows::Foundation::IInspectable>* self) noexcept
|
|
27
|
+
{
|
|
28
|
+
auto tp = Py_TYPE(self);
|
|
29
|
+
|
|
30
|
+
std::destroy_at(&self->obj);
|
|
31
|
+
tp->tp_free(self);
|
|
32
|
+
Py_DECREF(tp);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
PyDoc_STRVAR(
|
|
36
|
+
Object_iids_doc,
|
|
37
|
+
"Gets the interfaces that are implemented by the current Windows Runtime class.");
|
|
38
|
+
|
|
39
|
+
static PyObject* Object_iids_get(
|
|
40
|
+
py::winrt_wrapper<winrt::Windows::Foundation::IInspectable>* self,
|
|
41
|
+
void* /*unused*/) noexcept
|
|
42
|
+
{
|
|
43
|
+
try
|
|
44
|
+
{
|
|
45
|
+
auto name = winrt::get_interfaces(self->obj);
|
|
46
|
+
return convert(name);
|
|
47
|
+
}
|
|
48
|
+
catch (...)
|
|
49
|
+
{
|
|
50
|
+
py::to_PyErr();
|
|
51
|
+
return nullptr;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
PyDoc_STRVAR(
|
|
56
|
+
Object_runtime_class_name_doc,
|
|
57
|
+
"Gets the fully qualified name of the current Windows Runtime object.");
|
|
58
|
+
|
|
59
|
+
static PyObject* Object_runtime_class_name_get(
|
|
60
|
+
py::winrt_wrapper<winrt::Windows::Foundation::IInspectable>* self,
|
|
61
|
+
void* /*unused*/) noexcept
|
|
62
|
+
{
|
|
63
|
+
try
|
|
64
|
+
{
|
|
65
|
+
auto name = winrt::get_class_name(self->obj);
|
|
66
|
+
return convert(name);
|
|
67
|
+
}
|
|
68
|
+
catch (...)
|
|
69
|
+
{
|
|
70
|
+
py::to_PyErr();
|
|
71
|
+
return nullptr;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static PyGetSetDef Object_getset[]
|
|
76
|
+
= {{"_iids_",
|
|
77
|
+
reinterpret_cast<getter>(Object_iids_get),
|
|
78
|
+
nullptr,
|
|
79
|
+
Object_iids_doc,
|
|
80
|
+
nullptr},
|
|
81
|
+
{"_runtime_class_name_",
|
|
82
|
+
reinterpret_cast<getter>(Object_runtime_class_name_get),
|
|
83
|
+
nullptr,
|
|
84
|
+
Object_runtime_class_name_doc,
|
|
85
|
+
nullptr},
|
|
86
|
+
{}};
|
|
87
|
+
|
|
88
|
+
static PyType_Slot Object_type_slots[]
|
|
89
|
+
= {{Py_tp_doc, const_cast<char*>(Object_doc)},
|
|
90
|
+
{Py_tp_new, reinterpret_cast<void*>(Object_new)},
|
|
91
|
+
{Py_tp_dealloc, reinterpret_cast<void*>(Object_dealloc)},
|
|
92
|
+
{Py_tp_getset, reinterpret_cast<void*>(Object_getset)},
|
|
93
|
+
{}};
|
|
94
|
+
|
|
95
|
+
static PyType_Spec Object_type_spec
|
|
96
|
+
= {"_winrt.Object",
|
|
97
|
+
sizeof(py::winrt_wrapper<winrt::Windows::Foundation::IUnknown>),
|
|
98
|
+
0,
|
|
99
|
+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
|
100
|
+
Object_type_slots};
|
|
101
|
+
|
|
102
|
+
// END: class _winrt.Object:
|
|
103
|
+
|
|
104
|
+
// BEGIN: class _winrt.Array:
|
|
105
|
+
|
|
106
|
+
extern PyType_Spec Array_type_spec;
|
|
107
|
+
|
|
108
|
+
// END: class _winrt.Array:
|
|
109
|
+
|
|
110
|
+
// BEGIN: class _winrt.MappingIter:
|
|
111
|
+
|
|
112
|
+
// This class is used to wrap the iterator returned by IMap/IMapView so
|
|
113
|
+
// that it returns only the key instead of a KeyValuePair. This is done
|
|
114
|
+
// to be consistent with the Python mapping protocol.
|
|
115
|
+
//
|
|
116
|
+
// In Python it would look something like this:
|
|
117
|
+
//
|
|
118
|
+
// class MappingIter:
|
|
119
|
+
// def __init__(self, base_iter):
|
|
120
|
+
// self._iter = iter(base_iter)
|
|
121
|
+
//
|
|
122
|
+
// def __iter__(self):
|
|
123
|
+
// return self
|
|
124
|
+
//
|
|
125
|
+
// def __next__(self):
|
|
126
|
+
// return next(self._iter).key
|
|
127
|
+
//
|
|
128
|
+
|
|
129
|
+
struct MappingIter_object
|
|
130
|
+
{
|
|
131
|
+
PyObject_HEAD;
|
|
132
|
+
PyObject* _iter;
|
|
133
|
+
PyObject* _key;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
static PyMemberDef MappingIter_members[]
|
|
137
|
+
= {{"_iter",
|
|
138
|
+
T_OBJECT_EX,
|
|
139
|
+
offsetof(MappingIter_object, _iter),
|
|
140
|
+
0,
|
|
141
|
+
PyDoc_STR("base KeyValuePair iterator")},
|
|
142
|
+
{"_key", T_OBJECT, offsetof(MappingIter_object, _key), 0, nullptr},
|
|
143
|
+
{}};
|
|
144
|
+
|
|
145
|
+
static int MappingIter_init(PyObject* self, PyObject* args, PyObject* kwds) noexcept
|
|
146
|
+
{
|
|
147
|
+
if (kwds)
|
|
148
|
+
{
|
|
149
|
+
PyErr_SetString(PyExc_TypeError, "keyword arguments are not supported");
|
|
150
|
+
return -1;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// borrowed ref
|
|
154
|
+
auto base_iter = PyTuple_GetItem(args, 0);
|
|
155
|
+
|
|
156
|
+
if (!base_iter)
|
|
157
|
+
{
|
|
158
|
+
return -1;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!PyIter_Check(base_iter))
|
|
162
|
+
{
|
|
163
|
+
PyErr_SetString(PyExc_TypeError, "expecting an iterator");
|
|
164
|
+
return -1;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (PyObject_SetAttrString(self, "_iter", base_iter) == -1)
|
|
168
|
+
{
|
|
169
|
+
return -1;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
py::pyobj_handle key{PyUnicode_FromString("key")};
|
|
173
|
+
if (!key)
|
|
174
|
+
{
|
|
175
|
+
return -1;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (PyObject_SetAttrString(self, "_key", key.get()) == -1)
|
|
179
|
+
{
|
|
180
|
+
return -1;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
static PyObject* MappingIter_iternext(MappingIter_object* self) noexcept
|
|
187
|
+
{
|
|
188
|
+
if (!self->_iter)
|
|
189
|
+
{
|
|
190
|
+
PyErr_SetString(PyExc_RuntimeError, "_iter was deleted");
|
|
191
|
+
return nullptr;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
py::pyobj_handle next{PyIter_Next(self->_iter)};
|
|
195
|
+
if (!next)
|
|
196
|
+
{
|
|
197
|
+
return nullptr;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!self->_key)
|
|
201
|
+
{
|
|
202
|
+
PyErr_SetString(PyExc_RuntimeError, "_key was deleted");
|
|
203
|
+
return nullptr;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
py::pyobj_handle key{PyObject_GetAttr(next.get(), self->_key)};
|
|
207
|
+
if (!key)
|
|
208
|
+
{
|
|
209
|
+
return nullptr;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return key.detach();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
PyDoc_STRVAR(MappingIter_doc, "Utility class for wrapping KeyValuePair iterators.");
|
|
216
|
+
|
|
217
|
+
static PyType_Slot MappingIter_type_slots[] = {
|
|
218
|
+
{Py_tp_members, reinterpret_cast<void*>(MappingIter_members)},
|
|
219
|
+
{Py_tp_init, reinterpret_cast<void*>(MappingIter_init)},
|
|
220
|
+
{Py_tp_iter, reinterpret_cast<void*>(PyObject_SelfIter)},
|
|
221
|
+
{Py_tp_iternext, reinterpret_cast<void*>(MappingIter_iternext)},
|
|
222
|
+
{Py_tp_doc, const_cast<char*>(MappingIter_doc)},
|
|
223
|
+
{},
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
static PyType_Spec MappingIter_type_spec
|
|
227
|
+
= {"_winrt.MappingIter",
|
|
228
|
+
sizeof(MappingIter_object),
|
|
229
|
+
0,
|
|
230
|
+
Py_TPFLAGS_DEFAULT,
|
|
231
|
+
MappingIter_type_slots};
|
|
232
|
+
|
|
233
|
+
// END: class _winrt.MappingIter:
|
|
234
|
+
|
|
235
|
+
static const py::runtime_api runtime_api{
|
|
236
|
+
.runtime_api_guid = py::runtime_api_guid,
|
|
237
|
+
.abi_version_major = py::runtime_abi_version_major,
|
|
238
|
+
.abi_version_minor = py::runtime_abi_version_minor,
|
|
239
|
+
.register_python_type = py::register_python_type,
|
|
240
|
+
.get_python_type = py::get_python_type,
|
|
241
|
+
.wrap_mapping_iter = py::wrap_mapping_iter,
|
|
242
|
+
.is_buffer_compatible = py::is_buffer_compatible,
|
|
243
|
+
.convert_datetime = py::convert_datetime,
|
|
244
|
+
.convert_to_datetime = py::convert_to_datetime,
|
|
245
|
+
.convert_guid = py::convert_guid,
|
|
246
|
+
.convert_to_guid = py::convert_to_guid,
|
|
247
|
+
.get_object_type = py::get_object_type,
|
|
248
|
+
.array_new = py::cpp::_winrt::Array_New,
|
|
249
|
+
.array_assign = &py::cpp::_winrt::Array_Assign,
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
static PyObject* init_apartment(PyObject* /*unused*/, PyObject* type_obj) noexcept
|
|
253
|
+
{
|
|
254
|
+
auto type = PyLong_AsLong(type_obj);
|
|
255
|
+
|
|
256
|
+
if (type == -1 && PyErr_Occurred())
|
|
257
|
+
{
|
|
258
|
+
return nullptr;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
try
|
|
262
|
+
{
|
|
263
|
+
winrt::init_apartment(static_cast<winrt::apartment_type>(type));
|
|
264
|
+
Py_RETURN_NONE;
|
|
265
|
+
}
|
|
266
|
+
catch (...)
|
|
267
|
+
{
|
|
268
|
+
py::to_PyErr();
|
|
269
|
+
return nullptr;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
static PyObject* uninit_apartment(
|
|
274
|
+
PyObject* /*unused*/, PyObject* /*unused*/) noexcept
|
|
275
|
+
{
|
|
276
|
+
winrt::uninit_apartment();
|
|
277
|
+
Py_RETURN_NONE;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
static PyObject* initialize_with_window(
|
|
281
|
+
PyObject* /*unused*/, PyObject* args) noexcept
|
|
282
|
+
{
|
|
283
|
+
PyObject* obj;
|
|
284
|
+
Py_ssize_t hwnd;
|
|
285
|
+
|
|
286
|
+
if (!PyArg_ParseTuple(args, "On", &obj, &hwnd))
|
|
287
|
+
{
|
|
288
|
+
return nullptr;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
try
|
|
292
|
+
{
|
|
293
|
+
auto winrt_obj
|
|
294
|
+
= py::convert_to<winrt::Windows::Foundation::IInspectable>(obj);
|
|
295
|
+
auto result = winrt_obj.as<IInitializeWithWindow>()->Initialize(
|
|
296
|
+
reinterpret_cast<HWND>(hwnd));
|
|
297
|
+
|
|
298
|
+
if (result != S_OK)
|
|
299
|
+
{
|
|
300
|
+
winrt::throw_hresult(result);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch (...)
|
|
304
|
+
{
|
|
305
|
+
py::to_PyErr();
|
|
306
|
+
return nullptr;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
Py_RETURN_NONE;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
static PyObject* add_dll_directory(PyObject* /*unused*/, PyObject* obj) noexcept
|
|
313
|
+
{
|
|
314
|
+
std::unique_ptr<wchar_t, decltype(&PyMem_Free)> path{
|
|
315
|
+
PyUnicode_AsWideCharString(obj, nullptr), &PyMem_Free};
|
|
316
|
+
|
|
317
|
+
if (!path)
|
|
318
|
+
{
|
|
319
|
+
return nullptr;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
auto cookie = AddDllDirectory(path.get());
|
|
323
|
+
|
|
324
|
+
if (!cookie)
|
|
325
|
+
{
|
|
326
|
+
PyErr_SetFromWindowsErr(GetLastError());
|
|
327
|
+
return nullptr;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return PyLong_FromVoidPtr(cookie);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
static PyObject* remove_dll_directory(PyObject* /*unused*/, PyObject* obj) noexcept
|
|
334
|
+
{
|
|
335
|
+
auto cookie = PyLong_AsVoidPtr(obj);
|
|
336
|
+
if (!cookie && PyErr_Occurred())
|
|
337
|
+
{
|
|
338
|
+
return nullptr;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (!RemoveDllDirectory(cookie))
|
|
342
|
+
{
|
|
343
|
+
PyErr_SetFromWindowsErr(GetLastError());
|
|
344
|
+
return nullptr;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
Py_RETURN_NONE;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Equivalent to functools.cache(functools.partial(uuid.UUID, None))
|
|
352
|
+
*
|
|
353
|
+
* This is a performance optimization since the UUID constructor is expensive.
|
|
354
|
+
*/
|
|
355
|
+
static PyObject* wrap_uuid_constructor() noexcept
|
|
356
|
+
{
|
|
357
|
+
pyobj_handle uuid_module{PyImport_ImportModule("uuid")};
|
|
358
|
+
if (!uuid_module)
|
|
359
|
+
{
|
|
360
|
+
return nullptr;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
pyobj_handle uuid_type{PyObject_GetAttrString(uuid_module.get(), "UUID")};
|
|
364
|
+
if (!uuid_type)
|
|
365
|
+
{
|
|
366
|
+
return nullptr;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
pyobj_handle functools_module{PyImport_ImportModule("functools")};
|
|
370
|
+
if (!functools_module)
|
|
371
|
+
{
|
|
372
|
+
return nullptr;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
pyobj_handle partial_func{
|
|
376
|
+
PyObject_GetAttrString(functools_module.get(), "partial")};
|
|
377
|
+
if (!partial_func)
|
|
378
|
+
{
|
|
379
|
+
return nullptr;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
pyobj_handle partial_uuid_func{PyObject_CallFunctionObjArgs(
|
|
383
|
+
partial_func.get(), uuid_type.get(), Py_None, nullptr)};
|
|
384
|
+
if (!partial_uuid_func)
|
|
385
|
+
{
|
|
386
|
+
return nullptr;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// REVISIT: we could probably implement a cache function in C++ that
|
|
390
|
+
// would even more performant
|
|
391
|
+
pyobj_handle cache_func{
|
|
392
|
+
PyObject_GetAttrString(functools_module.get(), "cache")};
|
|
393
|
+
if (!cache_func)
|
|
394
|
+
{
|
|
395
|
+
return nullptr;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return PyObject_CallOneArg(cache_func.get(), partial_uuid_func.get());
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
static int module_traverse(PyObject* module, visitproc visit, void* arg) noexcept
|
|
402
|
+
{
|
|
403
|
+
auto state = reinterpret_cast<module_state*>(PyModule_GetState(module));
|
|
404
|
+
|
|
405
|
+
Py_VISIT(state->object_type);
|
|
406
|
+
Py_VISIT(state->array_type);
|
|
407
|
+
Py_VISIT(state->mapping_iter_type);
|
|
408
|
+
Py_VISIT(state->to_uuid_func);
|
|
409
|
+
|
|
410
|
+
for (const auto& [key, value] : state->type_cache)
|
|
411
|
+
{
|
|
412
|
+
Py_VISIT(value);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
return 0;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
static int module_clear(PyObject* module) noexcept
|
|
419
|
+
{
|
|
420
|
+
auto state = reinterpret_cast<module_state*>(PyModule_GetState(module));
|
|
421
|
+
|
|
422
|
+
Py_CLEAR(state->object_type);
|
|
423
|
+
Py_CLEAR(state->array_type);
|
|
424
|
+
Py_CLEAR(state->mapping_iter_type);
|
|
425
|
+
Py_CLEAR(state->to_uuid_func);
|
|
426
|
+
|
|
427
|
+
auto type_cache = std::move(state->type_cache);
|
|
428
|
+
|
|
429
|
+
for (auto& [key, value] : type_cache)
|
|
430
|
+
{
|
|
431
|
+
Py_XDECREF(value);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return 0;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
static void module_free(PyObject* module) noexcept
|
|
438
|
+
{
|
|
439
|
+
auto state = reinterpret_cast<module_state*>(PyModule_GetState(module));
|
|
440
|
+
|
|
441
|
+
Py_XDECREF(state->object_type);
|
|
442
|
+
Py_XDECREF(state->array_type);
|
|
443
|
+
Py_XDECREF(state->mapping_iter_type);
|
|
444
|
+
Py_XDECREF(state->to_uuid_func);
|
|
445
|
+
|
|
446
|
+
for (auto& [key, value] : state->type_cache)
|
|
447
|
+
{
|
|
448
|
+
Py_XDECREF(value);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
std::destroy_at(&state->type_cache);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
PyDoc_STRVAR(module_doc, "_winrt");
|
|
455
|
+
|
|
456
|
+
static PyMethodDef module_methods[]{
|
|
457
|
+
{"init_apartment", init_apartment, METH_O, "initialize the apartment"},
|
|
458
|
+
{"uninit_apartment",
|
|
459
|
+
uninit_apartment,
|
|
460
|
+
METH_NOARGS,
|
|
461
|
+
PyDoc_STR("uninitialize the apartment")},
|
|
462
|
+
{"initialize_with_window",
|
|
463
|
+
initialize_with_window,
|
|
464
|
+
METH_VARARGS,
|
|
465
|
+
PyDoc_STR(
|
|
466
|
+
"interop function to invoke IInitializeWithWindow::Initialize on an object")},
|
|
467
|
+
{"_add_dll_directory",
|
|
468
|
+
add_dll_directory,
|
|
469
|
+
METH_O,
|
|
470
|
+
PyDoc_STR("Adds a directory to the DLL search path.")},
|
|
471
|
+
{"_remove_dll_directory",
|
|
472
|
+
remove_dll_directory,
|
|
473
|
+
METH_O,
|
|
474
|
+
PyDoc_STR(
|
|
475
|
+
"Removes a directory that was added to the process DLL search path by using _add_dll_directory.")},
|
|
476
|
+
{}};
|
|
477
|
+
|
|
478
|
+
static PyModuleDef module_def
|
|
479
|
+
= {PyModuleDef_HEAD_INIT,
|
|
480
|
+
"_winrt",
|
|
481
|
+
module_doc,
|
|
482
|
+
sizeof(module_state),
|
|
483
|
+
module_methods,
|
|
484
|
+
nullptr,
|
|
485
|
+
module_traverse,
|
|
486
|
+
module_clear,
|
|
487
|
+
reinterpret_cast<freefunc>(module_free)};
|
|
488
|
+
|
|
489
|
+
static PyObject* module_init() noexcept
|
|
490
|
+
{
|
|
491
|
+
static const auto kMTA
|
|
492
|
+
= static_cast<long>(winrt::apartment_type::multi_threaded);
|
|
493
|
+
static const auto kSTA
|
|
494
|
+
= static_cast<long>(winrt::apartment_type::single_threaded);
|
|
495
|
+
|
|
496
|
+
py::pyobj_handle module{PyModule_Create(&module_def)};
|
|
497
|
+
if (!module)
|
|
498
|
+
{
|
|
499
|
+
return nullptr;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
auto state = reinterpret_cast<module_state*>(PyModule_GetState(module.get()));
|
|
503
|
+
std::construct_at(&state->type_cache);
|
|
504
|
+
|
|
505
|
+
py::pytype_handle object_type{py::register_python_type(
|
|
506
|
+
module.get(), &Object_type_spec, nullptr, nullptr)};
|
|
507
|
+
if (!object_type)
|
|
508
|
+
{
|
|
509
|
+
return nullptr;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
py::pytype_handle array_type{
|
|
513
|
+
py::register_python_type(module.get(), &Array_type_spec, nullptr, nullptr)};
|
|
514
|
+
if (!array_type)
|
|
515
|
+
{
|
|
516
|
+
return nullptr;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
py::pytype_handle mapping_iter_type{py::register_python_type(
|
|
520
|
+
module.get(), &MappingIter_type_spec, nullptr, nullptr)};
|
|
521
|
+
if (!mapping_iter_type)
|
|
522
|
+
{
|
|
523
|
+
return nullptr;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
pyobj_handle runtime_api_capsule{PyCapsule_New(
|
|
527
|
+
const_cast<py::runtime_api*>(&runtime_api),
|
|
528
|
+
"winrt._winrt._C_API",
|
|
529
|
+
nullptr)};
|
|
530
|
+
|
|
531
|
+
if (!runtime_api_capsule)
|
|
532
|
+
{
|
|
533
|
+
return nullptr;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (PyModule_AddObjectRef(module.get(), "_C_API", runtime_api_capsule.get())
|
|
537
|
+
== -1)
|
|
538
|
+
{
|
|
539
|
+
return nullptr;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (PyModule_AddIntConstant(module.get(), "MTA", kMTA) == -1)
|
|
543
|
+
{
|
|
544
|
+
return nullptr;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (PyModule_AddIntConstant(module.get(), "STA", kSTA) == -1)
|
|
548
|
+
{
|
|
549
|
+
return nullptr;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
pyobj_handle to_uuid_func{wrap_uuid_constructor()};
|
|
553
|
+
if (!to_uuid_func)
|
|
554
|
+
{
|
|
555
|
+
return nullptr;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
state->object_type = object_type.detach();
|
|
559
|
+
state->array_type = array_type.detach();
|
|
560
|
+
state->mapping_iter_type = mapping_iter_type.detach();
|
|
561
|
+
state->to_uuid_func = to_uuid_func.detach();
|
|
562
|
+
|
|
563
|
+
return module.detach();
|
|
564
|
+
}
|
|
565
|
+
} // namespace py::cpp::_winrt
|
|
566
|
+
|
|
567
|
+
PyMODINIT_FUNC PyInit__winrt(void) noexcept
|
|
568
|
+
{
|
|
569
|
+
return py::cpp::_winrt::module_init();
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
py::cpp::_winrt::module_state* py::cpp::_winrt::get_module_state() noexcept
|
|
573
|
+
{
|
|
574
|
+
auto module = PyState_FindModule(&py::cpp::_winrt::module_def);
|
|
575
|
+
if (!module)
|
|
576
|
+
{
|
|
577
|
+
return nullptr;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return reinterpret_cast<py::cpp::_winrt::module_state*>(PyModule_GetState(module));
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
PyTypeObject* py::get_object_type() noexcept
|
|
584
|
+
{
|
|
585
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
586
|
+
if (!state)
|
|
587
|
+
{
|
|
588
|
+
return nullptr;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return state->object_type;
|
|
592
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#define PYWINRT_RUNTIME_MODULE
|
|
2
2
|
#include "pybase.h"
|
|
3
|
+
#include "pyruntime.h"
|
|
3
4
|
#include "py.Windows.Foundation.h"
|
|
4
5
|
#include <winrt/base.h>
|
|
5
6
|
|
|
@@ -538,36 +539,13 @@ namespace py::cpp::_winrt
|
|
|
538
539
|
|
|
539
540
|
static PyTypeObject* get_array_type() noexcept
|
|
540
541
|
{
|
|
541
|
-
py::
|
|
542
|
-
|
|
543
|
-
if (!system_module)
|
|
544
|
-
{
|
|
545
|
-
return nullptr;
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
py::pyobj_handle array_type{
|
|
549
|
-
PyObject_GetAttrString(system_module.get(), "Array")};
|
|
550
|
-
|
|
551
|
-
if (!array_type)
|
|
552
|
-
{
|
|
553
|
-
return nullptr;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
if (!PyType_Check(array_type.get()))
|
|
557
|
-
{
|
|
558
|
-
PyErr_SetString(
|
|
559
|
-
PyExc_TypeError, "winrt.system.Array is not a type object!");
|
|
560
|
-
return nullptr;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
if (reinterpret_cast<PyTypeObject*>(array_type.get())->tp_new != Array_tp_new)
|
|
542
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
543
|
+
if (!state)
|
|
564
544
|
{
|
|
565
|
-
PyErr_SetString(
|
|
566
|
-
PyExc_TypeError, "winrt.system.Array is not the expected type!");
|
|
567
545
|
return nullptr;
|
|
568
546
|
}
|
|
569
547
|
|
|
570
|
-
return
|
|
548
|
+
return state->array_type;
|
|
571
549
|
}
|
|
572
550
|
|
|
573
551
|
} // namespace py::cpp::_winrt
|
|
@@ -16,7 +16,7 @@ classifiers = [
|
|
|
16
16
|
"Intended Audience :: Developers",
|
|
17
17
|
]
|
|
18
18
|
dynamic = ["version"]
|
|
19
|
-
requires-python = ">=3.9,<3.
|
|
19
|
+
requires-python = ">=3.9,<3.14"
|
|
20
20
|
|
|
21
21
|
[project.urls]
|
|
22
22
|
# Homepage = "https://github.com/pywinrt/pywinrt"
|
|
@@ -37,7 +37,8 @@ where = ["src"]
|
|
|
37
37
|
# use local winrt-sdk build dependency
|
|
38
38
|
environment = { PYTHONPATH="../winrt-sdk/src" }
|
|
39
39
|
# don't install winrt-sdk from PyPI
|
|
40
|
-
build-frontend = { name = "build", args = ["--skip-dependency-check", "--no-isolation"] }
|
|
40
|
+
build-frontend = { name = "build[uv]", args = ["--skip-dependency-check", "--no-isolation"] }
|
|
41
|
+
before-build = "uv pip install setuptools"
|
|
41
42
|
# don't build for PyPy
|
|
42
43
|
skip = "pp*"
|
|
43
44
|
# suppress warnings about ARM64 testing
|
|
@@ -45,4 +46,4 @@ test-skip = "*-win_arm64"
|
|
|
45
46
|
|
|
46
47
|
[tool.cibuildwheel.windows]
|
|
47
48
|
archs = ["x86", "AMD64", "ARM64"]
|
|
48
|
-
repair-wheel-command = "python scripts/
|
|
49
|
+
repair-wheel-command = "python scripts/add_msvcp140_dll.py {wheel} {dest_dir}"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.2.0
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
#define PYWINRT_RUNTIME_MODULE
|
|
8
8
|
#include "pybase.h"
|
|
9
|
+
#include "pyruntime.h"
|
|
9
10
|
|
|
10
11
|
// "backport" of Python 3.12 function.
|
|
11
12
|
#if PY_VERSION_HEX < 0x030C0000
|
|
@@ -168,30 +169,93 @@ static PyObject* PyType_FromMetaclass(
|
|
|
168
169
|
* @param base_type The base type, a tuple of base types or nullptr to use the base
|
|
169
170
|
* slot.
|
|
170
171
|
* @param metaclass Optional metaclass for the type.
|
|
171
|
-
* @returns
|
|
172
|
+
* @returns New reference on success or nullptr on error.
|
|
172
173
|
*/
|
|
173
174
|
|
|
174
|
-
|
|
175
|
+
PyTypeObject* py::register_python_type(
|
|
175
176
|
PyObject* module,
|
|
176
177
|
PyType_Spec* type_spec,
|
|
177
178
|
PyObject* base_type,
|
|
178
179
|
PyTypeObject* metaclass) noexcept
|
|
179
180
|
{
|
|
180
|
-
py::
|
|
181
|
-
PyType_FromMetaclass(metaclass, module, type_spec, base_type)};
|
|
181
|
+
py::pytype_handle type_object{reinterpret_cast<PyTypeObject*>(
|
|
182
|
+
PyType_FromMetaclass(metaclass, module, type_spec, base_type))};
|
|
182
183
|
|
|
183
184
|
if (!type_object)
|
|
184
185
|
{
|
|
185
|
-
return
|
|
186
|
+
return nullptr;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (PyModule_AddType(module, type_object.get()) == -1)
|
|
190
|
+
{
|
|
191
|
+
return nullptr;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return type_object.detach();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
PyTypeObject* py::get_python_type(std::string_view qualified_name) noexcept
|
|
198
|
+
{
|
|
199
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
200
|
+
if (!state)
|
|
201
|
+
{
|
|
202
|
+
return nullptr;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
auto it = state->type_cache.find(qualified_name);
|
|
206
|
+
if (it != state->type_cache.end())
|
|
207
|
+
{
|
|
208
|
+
return it->second;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
auto pos = qualified_name.find_last_of('.');
|
|
212
|
+
if (pos == std::string_view::npos)
|
|
213
|
+
{
|
|
214
|
+
PyErr_Format(
|
|
215
|
+
PyExc_ValueError, "invalid qualified name: %s", qualified_name.data());
|
|
216
|
+
return nullptr;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
std::string module_name{qualified_name.substr(0, pos)};
|
|
220
|
+
std::string type_name{qualified_name.substr(pos + 1)};
|
|
221
|
+
|
|
222
|
+
pyobj_handle module{PyImport_ImportModule(module_name.c_str())};
|
|
223
|
+
if (!module)
|
|
224
|
+
{
|
|
225
|
+
return nullptr;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
pyobj_handle type{PyObject_GetAttrString(module.get(), type_name.c_str())};
|
|
229
|
+
if (!type)
|
|
230
|
+
{
|
|
231
|
+
return nullptr;
|
|
186
232
|
}
|
|
187
233
|
|
|
188
|
-
if (
|
|
189
|
-
|
|
234
|
+
if (!PyType_Check(type.get()))
|
|
235
|
+
{
|
|
236
|
+
PyErr_Format(
|
|
237
|
+
PyExc_TypeError,
|
|
238
|
+
"'%s.%s' is not a type",
|
|
239
|
+
module_name.c_str(),
|
|
240
|
+
type_name.c_str());
|
|
241
|
+
return nullptr;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// TODO: verify that the Python type is compatible with the winrt
|
|
245
|
+
// runtime module version and that it actually matches the C++ type
|
|
246
|
+
|
|
247
|
+
try
|
|
248
|
+
{
|
|
249
|
+
state->type_cache[qualified_name]
|
|
250
|
+
= reinterpret_cast<PyTypeObject*>(Py_NewRef(type.get()));
|
|
251
|
+
}
|
|
252
|
+
catch (...)
|
|
190
253
|
{
|
|
191
|
-
|
|
254
|
+
to_PyErr();
|
|
255
|
+
return nullptr;
|
|
192
256
|
}
|
|
193
257
|
|
|
194
|
-
return
|
|
258
|
+
return reinterpret_cast<PyTypeObject*>(type.get());
|
|
195
259
|
}
|
|
196
260
|
|
|
197
261
|
/**
|
|
@@ -202,22 +266,14 @@ int py::register_python_type(
|
|
|
202
266
|
*/
|
|
203
267
|
PyObject* py::wrap_mapping_iter(PyObject* iter) noexcept
|
|
204
268
|
{
|
|
205
|
-
py::
|
|
206
|
-
|
|
207
|
-
if (!winrt_module)
|
|
208
|
-
{
|
|
209
|
-
return nullptr;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
py::pyobj_handle mapping_iter_type{
|
|
213
|
-
PyObject_GetAttrString(winrt_module.get(), "MappingIter")};
|
|
214
|
-
|
|
215
|
-
if (!mapping_iter_type)
|
|
269
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
270
|
+
if (!state)
|
|
216
271
|
{
|
|
217
272
|
return nullptr;
|
|
218
273
|
}
|
|
219
274
|
|
|
220
|
-
py::pyobj_handle wrapper{PyObject_CallOneArg(
|
|
275
|
+
py::pyobj_handle wrapper{PyObject_CallOneArg(
|
|
276
|
+
reinterpret_cast<PyObject*>(state->mapping_iter_type), iter)};
|
|
221
277
|
|
|
222
278
|
if (!wrapper)
|
|
223
279
|
{
|
|
@@ -393,3 +449,62 @@ winrt::Windows::Foundation::DateTime py::convert_to_datetime(PyObject* obj)
|
|
|
393
449
|
|
|
394
450
|
return value;
|
|
395
451
|
}
|
|
452
|
+
|
|
453
|
+
PyObject* py::convert_guid(winrt::guid value) noexcept
|
|
454
|
+
{
|
|
455
|
+
auto state = py::cpp::_winrt::get_module_state();
|
|
456
|
+
if (!state)
|
|
457
|
+
{
|
|
458
|
+
return nullptr;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// It is faster to swap in C++ rather than using bytes_le in Python since
|
|
462
|
+
// Python stores the bytes in a different order.
|
|
463
|
+
alignas(4) char buffer[sizeof(winrt::guid)];
|
|
464
|
+
*reinterpret_cast<uint32_t*>(buffer) = _byteswap_ulong(value.Data1);
|
|
465
|
+
*reinterpret_cast<uint16_t*>(buffer + 4) = _byteswap_ushort(value.Data2);
|
|
466
|
+
*reinterpret_cast<uint16_t*>(buffer + 6) = _byteswap_ushort(value.Data3);
|
|
467
|
+
std::memcpy(buffer + 8, value.Data4, sizeof(value.Data4));
|
|
468
|
+
|
|
469
|
+
pyobj_handle value_as_bytes{PyBytes_FromStringAndSize(buffer, sizeof(buffer))};
|
|
470
|
+
if (!value_as_bytes)
|
|
471
|
+
{
|
|
472
|
+
return nullptr;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
return PyObject_CallOneArg(state->to_uuid_func, value_as_bytes.get());
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
winrt::guid py::convert_to_guid(PyObject* obj)
|
|
479
|
+
{
|
|
480
|
+
throw_if_pyobj_null(obj);
|
|
481
|
+
|
|
482
|
+
pyobj_handle bytes{PyObject_GetAttrString(obj, "bytes")};
|
|
483
|
+
if (!bytes)
|
|
484
|
+
{
|
|
485
|
+
throw python_exception();
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
char* buffer;
|
|
489
|
+
Py_ssize_t size;
|
|
490
|
+
if (PyBytes_AsStringAndSize(bytes.get(), &buffer, &size) == -1)
|
|
491
|
+
{
|
|
492
|
+
throw python_exception();
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (size != sizeof(winrt::guid))
|
|
496
|
+
{
|
|
497
|
+
PyErr_SetString(PyExc_ValueError, "bytes is wrong size");
|
|
498
|
+
throw python_exception();
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// It is faster to swap in C++ rather than using bytes_le in Python since
|
|
502
|
+
// Python stores the bytes in a different order.
|
|
503
|
+
winrt::guid result;
|
|
504
|
+
result.Data1 = _byteswap_ulong(*reinterpret_cast<uint32_t*>(buffer));
|
|
505
|
+
result.Data2 = _byteswap_ushort(*reinterpret_cast<uint16_t*>(buffer + 4));
|
|
506
|
+
result.Data3 = _byteswap_ushort(*reinterpret_cast<uint16_t*>(buffer + 6));
|
|
507
|
+
std::memcpy(result.Data4, buffer + 8, sizeof(result.Data4));
|
|
508
|
+
|
|
509
|
+
return result;
|
|
510
|
+
}
|
|
@@ -16,6 +16,7 @@ from typing import (
|
|
|
16
16
|
ValuesView,
|
|
17
17
|
overload,
|
|
18
18
|
)
|
|
19
|
+
from uuid import UUID
|
|
19
20
|
|
|
20
21
|
MTA: int
|
|
21
22
|
STA: int
|
|
@@ -23,6 +24,8 @@ STA: int
|
|
|
23
24
|
def init_apartment(apartment_type: int) -> None: ...
|
|
24
25
|
def uninit_apartment() -> None: ...
|
|
25
26
|
def initialize_with_window(obj: Object, hwnd: int) -> None: ...
|
|
27
|
+
def _add_dll_directory(path: str) -> int: ...
|
|
28
|
+
def _remove_dll_directory(cookie: int) -> None: ...
|
|
26
29
|
|
|
27
30
|
_Self = TypeVar("_Self")
|
|
28
31
|
_T = TypeVar("_T")
|
|
@@ -82,7 +85,11 @@ class MutableMapping(Mapping[_KT, _VT]):
|
|
|
82
85
|
|
|
83
86
|
# actual runtime classes
|
|
84
87
|
|
|
85
|
-
class Object:
|
|
88
|
+
class Object:
|
|
89
|
+
@property
|
|
90
|
+
def _iids_(self) -> Array[UUID]: ...
|
|
91
|
+
@property
|
|
92
|
+
def _runtime_class_name_(self) -> str: ...
|
|
86
93
|
|
|
87
94
|
class Array(MutableSequence[_T]):
|
|
88
95
|
_winrt_element_type_name_: str
|
|
@@ -1,8 +1,38 @@
|
|
|
1
1
|
from collections.abc import Mapping, MutableMapping, MutableSequence, Sequence
|
|
2
|
+
from pathlib import Path
|
|
2
3
|
from typing import Annotated
|
|
3
4
|
|
|
4
5
|
from .. import _winrt
|
|
5
6
|
|
|
7
|
+
|
|
8
|
+
class _DllCookie:
|
|
9
|
+
def __init__(self, cookie: int) -> None:
|
|
10
|
+
self.cookie = cookie
|
|
11
|
+
|
|
12
|
+
def close(self):
|
|
13
|
+
if self.cookie:
|
|
14
|
+
_winrt._remove_dll_directory(self.cookie)
|
|
15
|
+
self.cookie = None
|
|
16
|
+
|
|
17
|
+
def __del__(self):
|
|
18
|
+
self.close()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _register_dll_search_path(module_path) -> _DllCookie:
|
|
22
|
+
"""
|
|
23
|
+
Register a module's directory as a DLL search path.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
module_path: The path to a module file (i.e. ``__file__``)
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
An cookie object that will remove the search path when closed.
|
|
30
|
+
"""
|
|
31
|
+
return _DllCookie(
|
|
32
|
+
_winrt._add_dll_directory(str(Path(module_path).parent.resolve()))
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
6
36
|
# NB: The types implemented in C cannot inherit from abc.ABC since Python 3.12
|
|
7
37
|
# so we have to implement the protocols like this instead.
|
|
8
38
|
# https://github.com/python/cpython/issues/103968#issuecomment-1589928055
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: winrt-runtime
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python projection of Windows Runtime (WinRT) APIs
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Documentation, https://pywinrt.readthedocs.io
|
|
@@ -10,7 +10,7 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
|
-
Requires-Python: <3.
|
|
13
|
+
Requires-Python: <3.14,>=3.9
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
|
|
16
16
|
# winrt-runtime
|
winrt_runtime-2.0.1/_winrt.cpp
DELETED
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
// must be included before winrt to avoid compile errors
|
|
2
|
-
#include <Shobjidl.h>
|
|
3
|
-
|
|
4
|
-
#define PYWINRT_RUNTIME_MODULE
|
|
5
|
-
#include "pybase.h"
|
|
6
|
-
#include <winrt/base.h>
|
|
7
|
-
|
|
8
|
-
namespace py::cpp::_winrt
|
|
9
|
-
{
|
|
10
|
-
// BEGIN: class _winrt.Object:
|
|
11
|
-
|
|
12
|
-
static constexpr const char* const type_name_Object = "Object";
|
|
13
|
-
|
|
14
|
-
PyDoc_STRVAR(Object_doc, "base class for wrapped WinRT object instances.");
|
|
15
|
-
|
|
16
|
-
static PyObject* Object_new(
|
|
17
|
-
PyTypeObject* /*unused*/, PyObject* /*unused*/, PyObject* /*unused*/) noexcept
|
|
18
|
-
{
|
|
19
|
-
py::set_invalid_activation_error(type_name_Object);
|
|
20
|
-
return nullptr;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
static void Object_dealloc(
|
|
24
|
-
py::winrt_wrapper<winrt::Windows::Foundation::IInspectable>* self)
|
|
25
|
-
{
|
|
26
|
-
auto tp = Py_TYPE(self);
|
|
27
|
-
|
|
28
|
-
std::destroy_at(&self->obj);
|
|
29
|
-
tp->tp_free(self);
|
|
30
|
-
Py_DECREF(tp);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
static PyType_Slot Object_type_slots[] = {
|
|
34
|
-
{Py_tp_new, reinterpret_cast<void*>(Object_new)},
|
|
35
|
-
{Py_tp_dealloc, reinterpret_cast<void*>(Object_dealloc)},
|
|
36
|
-
{Py_tp_doc, const_cast<char*>(Object_doc)},
|
|
37
|
-
{},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
static PyType_Spec Object_type_spec
|
|
41
|
-
= {"_winrt.Object",
|
|
42
|
-
sizeof(py::winrt_wrapper<winrt::Windows::Foundation::IUnknown>),
|
|
43
|
-
0,
|
|
44
|
-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
|
45
|
-
Object_type_slots};
|
|
46
|
-
|
|
47
|
-
// END: class _winrt.Object:
|
|
48
|
-
|
|
49
|
-
// BEGIN: class _winrt.Array:
|
|
50
|
-
|
|
51
|
-
extern PyType_Spec Array_type_spec;
|
|
52
|
-
|
|
53
|
-
// END: class _winrt.Array:
|
|
54
|
-
|
|
55
|
-
// BEGIN: class _winrt.MappingIter:
|
|
56
|
-
|
|
57
|
-
// This class is used to wrap the iterator returned by IMap/IMapView so
|
|
58
|
-
// that it returns only the key instead of a KeyValuePair. This is done
|
|
59
|
-
// to be consistent with the Python mapping protocol.
|
|
60
|
-
//
|
|
61
|
-
// In Python it would look something like this:
|
|
62
|
-
//
|
|
63
|
-
// class MappingIter:
|
|
64
|
-
// def __init__(self, base_iter):
|
|
65
|
-
// self._iter = iter(base_iter)
|
|
66
|
-
//
|
|
67
|
-
// def __iter__(self):
|
|
68
|
-
// return self
|
|
69
|
-
//
|
|
70
|
-
// def __next__(self):
|
|
71
|
-
// return next(self._iter).key
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
struct MappingIter_object
|
|
75
|
-
{
|
|
76
|
-
PyObject_HEAD;
|
|
77
|
-
PyObject* _iter;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
static PyMemberDef MappingIter_members[]
|
|
81
|
-
= {{"_iter",
|
|
82
|
-
T_OBJECT_EX,
|
|
83
|
-
offsetof(MappingIter_object, _iter),
|
|
84
|
-
0,
|
|
85
|
-
PyDoc_STR("base KeyValuePair iterator")},
|
|
86
|
-
{}};
|
|
87
|
-
|
|
88
|
-
static int MappingIter_init(PyObject* self, PyObject* args, PyObject* kwds) noexcept
|
|
89
|
-
{
|
|
90
|
-
if (kwds)
|
|
91
|
-
{
|
|
92
|
-
PyErr_SetString(PyExc_TypeError, "keyword arguments are not supported");
|
|
93
|
-
return -1;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// borrowed ref
|
|
97
|
-
auto base_iter = PyTuple_GetItem(args, 0);
|
|
98
|
-
|
|
99
|
-
if (!base_iter)
|
|
100
|
-
{
|
|
101
|
-
return -1;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (!PyIter_Check(base_iter))
|
|
105
|
-
{
|
|
106
|
-
PyErr_SetString(PyExc_TypeError, "expecting an iterator");
|
|
107
|
-
return -1;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (PyObject_SetAttrString(self, "_iter", base_iter) == -1)
|
|
111
|
-
{
|
|
112
|
-
return -1;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return 0;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
static PyObject* MappingIter_iternext(PyObject* self) noexcept
|
|
119
|
-
{
|
|
120
|
-
// new reference
|
|
121
|
-
py::pyobj_handle base_iter{PyObject_GetAttrString(self, "_iter")};
|
|
122
|
-
|
|
123
|
-
if (!base_iter)
|
|
124
|
-
{
|
|
125
|
-
return nullptr;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// new reference
|
|
129
|
-
py::pyobj_handle next{PyIter_Next(base_iter.get())};
|
|
130
|
-
|
|
131
|
-
if (!next)
|
|
132
|
-
{
|
|
133
|
-
return nullptr;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// new reference
|
|
137
|
-
py::pyobj_handle key{PyObject_GetAttrString(next.get(), "key")};
|
|
138
|
-
|
|
139
|
-
if (!key)
|
|
140
|
-
{
|
|
141
|
-
return nullptr;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return key.detach();
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
PyDoc_STRVAR(MappingIter_doc, "Utility class for wrapping KeyValuePair iterators.");
|
|
148
|
-
|
|
149
|
-
static PyType_Slot MappingIter_type_slots[] = {
|
|
150
|
-
{Py_tp_members, reinterpret_cast<void*>(MappingIter_members)},
|
|
151
|
-
{Py_tp_init, reinterpret_cast<void*>(MappingIter_init)},
|
|
152
|
-
{Py_tp_iter, reinterpret_cast<void*>(PyObject_SelfIter)},
|
|
153
|
-
{Py_tp_iternext, reinterpret_cast<void*>(MappingIter_iternext)},
|
|
154
|
-
{Py_tp_doc, const_cast<char*>(MappingIter_doc)},
|
|
155
|
-
{},
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
static PyType_Spec MappingIter_type_spec
|
|
159
|
-
= {"_winrt.MappingIter",
|
|
160
|
-
sizeof(MappingIter_object),
|
|
161
|
-
0,
|
|
162
|
-
Py_TPFLAGS_DEFAULT,
|
|
163
|
-
MappingIter_type_slots};
|
|
164
|
-
|
|
165
|
-
// END: class _winrt.MappingIter:
|
|
166
|
-
|
|
167
|
-
static const py::runtime_api runtime_api{
|
|
168
|
-
.runtime_api_guid = py::runtime_api_guid,
|
|
169
|
-
.abi_version_major = py::runtime_abi_version_major,
|
|
170
|
-
.abi_version_minor = py::runtime_abi_version_minor,
|
|
171
|
-
.register_python_type = py::register_python_type,
|
|
172
|
-
.wrap_mapping_iter = py::wrap_mapping_iter,
|
|
173
|
-
.is_buffer_compatible = py::is_buffer_compatible,
|
|
174
|
-
.convert_datetime = py::convert_datetime,
|
|
175
|
-
.convert_to_datetime = py::convert_to_datetime,
|
|
176
|
-
.get_object_type = py::get_object_type,
|
|
177
|
-
.array_new = py::cpp::_winrt::Array_New,
|
|
178
|
-
.array_assign = &py::cpp::_winrt::Array_Assign,
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
static PyObject* init_apartment(PyObject* /*unused*/, PyObject* type_obj) noexcept
|
|
182
|
-
{
|
|
183
|
-
auto type = PyLong_AsLong(type_obj);
|
|
184
|
-
|
|
185
|
-
if (type == -1 && PyErr_Occurred())
|
|
186
|
-
{
|
|
187
|
-
return nullptr;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
try
|
|
191
|
-
{
|
|
192
|
-
winrt::init_apartment(static_cast<winrt::apartment_type>(type));
|
|
193
|
-
Py_RETURN_NONE;
|
|
194
|
-
}
|
|
195
|
-
catch (...)
|
|
196
|
-
{
|
|
197
|
-
py::to_PyErr();
|
|
198
|
-
return nullptr;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
static PyObject* uninit_apartment(
|
|
203
|
-
PyObject* /*unused*/, PyObject* /*unused*/) noexcept
|
|
204
|
-
{
|
|
205
|
-
winrt::uninit_apartment();
|
|
206
|
-
Py_RETURN_NONE;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
static PyObject* initialize_with_window(
|
|
210
|
-
PyObject* /*unused*/, PyObject* args) noexcept
|
|
211
|
-
{
|
|
212
|
-
PyObject* obj;
|
|
213
|
-
Py_ssize_t hwnd;
|
|
214
|
-
|
|
215
|
-
if (!PyArg_ParseTuple(args, "On", &obj, &hwnd))
|
|
216
|
-
{
|
|
217
|
-
return nullptr;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
try
|
|
221
|
-
{
|
|
222
|
-
auto winrt_obj
|
|
223
|
-
= py::convert_to<winrt::Windows::Foundation::IInspectable>(obj);
|
|
224
|
-
auto result = winrt_obj.as<IInitializeWithWindow>()->Initialize(
|
|
225
|
-
reinterpret_cast<HWND>(hwnd));
|
|
226
|
-
|
|
227
|
-
if (result != S_OK)
|
|
228
|
-
{
|
|
229
|
-
winrt::throw_hresult(result);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
catch (...)
|
|
233
|
-
{
|
|
234
|
-
py::to_PyErr();
|
|
235
|
-
return nullptr;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
Py_RETURN_NONE;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
PyDoc_STRVAR(module_doc, "_winrt");
|
|
242
|
-
|
|
243
|
-
static PyMethodDef module_methods[]{
|
|
244
|
-
{"init_apartment", init_apartment, METH_O, "initialize the apartment"},
|
|
245
|
-
{"uninit_apartment",
|
|
246
|
-
uninit_apartment,
|
|
247
|
-
METH_NOARGS,
|
|
248
|
-
"uninitialize the apartment"},
|
|
249
|
-
{"initialize_with_window",
|
|
250
|
-
initialize_with_window,
|
|
251
|
-
METH_VARARGS,
|
|
252
|
-
"interop function to invoke IInitializeWithWindow::Initialize on an object"},
|
|
253
|
-
{}};
|
|
254
|
-
|
|
255
|
-
static PyModuleDef module_def
|
|
256
|
-
= {PyModuleDef_HEAD_INIT,
|
|
257
|
-
"_winrt",
|
|
258
|
-
module_doc,
|
|
259
|
-
0,
|
|
260
|
-
module_methods,
|
|
261
|
-
nullptr,
|
|
262
|
-
nullptr,
|
|
263
|
-
nullptr,
|
|
264
|
-
nullptr};
|
|
265
|
-
|
|
266
|
-
static PyObject* module_init() noexcept
|
|
267
|
-
{
|
|
268
|
-
static const auto kMTA
|
|
269
|
-
= static_cast<long>(winrt::apartment_type::multi_threaded);
|
|
270
|
-
static const auto kSTA
|
|
271
|
-
= static_cast<long>(winrt::apartment_type::single_threaded);
|
|
272
|
-
|
|
273
|
-
py::pyobj_handle module{PyModule_Create(&module_def)};
|
|
274
|
-
|
|
275
|
-
if (!module)
|
|
276
|
-
{
|
|
277
|
-
return nullptr;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (py::register_python_type(module.get(), &Object_type_spec, nullptr, nullptr)
|
|
281
|
-
== -1)
|
|
282
|
-
{
|
|
283
|
-
return nullptr;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (py::register_python_type(module.get(), &Array_type_spec, nullptr, nullptr)
|
|
287
|
-
== -1)
|
|
288
|
-
{
|
|
289
|
-
return nullptr;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (py::register_python_type(
|
|
293
|
-
module.get(), &MappingIter_type_spec, nullptr, nullptr)
|
|
294
|
-
== -1)
|
|
295
|
-
{
|
|
296
|
-
return nullptr;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
pyobj_handle runtime_api_capsule{PyCapsule_New(
|
|
300
|
-
const_cast<py::runtime_api*>(&runtime_api),
|
|
301
|
-
"winrt._winrt._C_API",
|
|
302
|
-
nullptr)};
|
|
303
|
-
|
|
304
|
-
if (!runtime_api_capsule)
|
|
305
|
-
{
|
|
306
|
-
return nullptr;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (PyModule_AddObjectRef(module.get(), "_C_API", runtime_api_capsule.get())
|
|
310
|
-
== -1)
|
|
311
|
-
{
|
|
312
|
-
return nullptr;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (PyModule_AddIntConstant(module.get(), "MTA", kMTA) == -1)
|
|
316
|
-
{
|
|
317
|
-
return nullptr;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (PyModule_AddIntConstant(module.get(), "STA", kSTA) == -1)
|
|
321
|
-
{
|
|
322
|
-
return nullptr;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return module.detach();
|
|
326
|
-
}
|
|
327
|
-
} // namespace py::cpp::_winrt
|
|
328
|
-
|
|
329
|
-
PyMODINIT_FUNC PyInit__winrt(void) noexcept
|
|
330
|
-
{
|
|
331
|
-
return py::cpp::_winrt::module_init();
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
PyTypeObject* py::get_object_type() noexcept
|
|
335
|
-
{
|
|
336
|
-
py::pyobj_handle system_module{PyImport_ImportModule("winrt.system")};
|
|
337
|
-
|
|
338
|
-
if (!system_module)
|
|
339
|
-
{
|
|
340
|
-
return nullptr;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
py::pyobj_handle object_type{PyObject_GetAttrString(system_module.get(), "Object")};
|
|
344
|
-
|
|
345
|
-
if (!object_type)
|
|
346
|
-
{
|
|
347
|
-
return nullptr;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
if (!PyType_Check(object_type.get()))
|
|
351
|
-
{
|
|
352
|
-
PyErr_SetString(PyExc_TypeError, "winrt.system.Object is not a type object!");
|
|
353
|
-
return nullptr;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
if (reinterpret_cast<PyTypeObject*>(object_type.get())->tp_new
|
|
357
|
-
!= py::cpp::_winrt::Object_new)
|
|
358
|
-
{
|
|
359
|
-
PyErr_SetString(
|
|
360
|
-
PyExc_TypeError, "winrt.system.Object is not the expected type!");
|
|
361
|
-
return nullptr;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
return reinterpret_cast<PyTypeObject*>(object_type.get());
|
|
365
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.0.1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|