winrt-runtime 4.0.1__tar.gz → 4.0.3__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-4.0.1/python/winrt_runtime.egg-info → winrt_runtime-4.0.3}/PKG-INFO +1 -1
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3/python/winrt_runtime.egg-info}/PKG-INFO +1 -1
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt_runtime.egg-info/SOURCES.txt +1 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/setup.py +1 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/_winrt.cpp +52 -6
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/compose.cpp +60 -26
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/compose.h +2 -2
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/delegates.cpp +7 -1
- winrt_runtime-4.0.3/src/handles.cpp +159 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/handles.h +26 -4
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/interp.cpp +1 -1
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/members.cpp +22 -18
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/objects.cpp +202 -14
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/objects.h +41 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/protocols.cpp +33 -8
- winrt_runtime-4.0.3/version.txt +1 -0
- winrt_runtime-4.0.1/version.txt +0 -1
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/LICENSE +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/MANIFEST.in +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/README.md +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/pyproject.toml +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/__pyinstaller/__init__.py +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/__pyinstaller/hook-winrt.py +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/_winrt.pyi +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/py.typed +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/runtime/__init__.py +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/runtime/_internals.py +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/runtime/interop.py +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/runtime/py.typed +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/system/__init__.py +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/system/hresult.py +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt/system/py.typed +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt_runtime.egg-info/dependency_links.txt +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt_runtime.egg-info/entry_points.txt +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt_runtime.egg-info/requires.txt +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/python/winrt_runtime.egg-info/top_level.txt +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/requirements.txt +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/setup.cfg +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/_winrt_array.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/_winrt_array.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/_winrt_box.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/_winrt_buffer.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/_winrt_buffer.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/arrays.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/arrays.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/async.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/async.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/callbacks.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/callbacks.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/collections.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/collections.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/delegates.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/enums.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/enums.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/errors.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/generics.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/generics.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/implements.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/implements.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/Windows.Foundation.Collections.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/Windows.Foundation.Metadata.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/Windows.Foundation.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/Windows.Storage.Streams.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/Windows.Storage.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/base.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/base_macros.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Devices.Geolocation.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Devices.Geolocation.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Foundation.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Foundation.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Foundation.2.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Foundation.Collections.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Foundation.Collections.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Foundation.Collections.2.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Foundation.Metadata.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Foundation.Metadata.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Foundation.Metadata.2.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.2.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.FileProperties.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.FileProperties.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.FileProperties.2.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.Provider.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.Provider.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.Provider.2.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.Search.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.Search.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.Search.2.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.Streams.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.Streams.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.Storage.Streams.2.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.System.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.System.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.System.2.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.System.RemoteSystems.0.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/cppwinrt/winrt/impl/Windows.System.RemoteSystems.1.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pythoncapi_compat.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/abi.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/array.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/async.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/base.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/buffer.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/convert.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/errors.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/prelude.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/throw_helpers.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/traits.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/include/pywinrt/wrappers.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/interp.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/members.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/metaclass.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/module_state.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/numerics-buffer.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/numerics-buffer.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/numerics-statics.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/numerics-statics.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/numerics-traits.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/numerics-values.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/numerics.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/numerics.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/protocols.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/pycollections.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/pycollections.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/pymapping.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/pymapping.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/pysequence.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/pysequence.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/runtime.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/runtime.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/shapes-generated.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/shapes.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/shapes.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/structs.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/structs.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/table.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/table.h +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/types.cpp +0 -0
- {winrt_runtime-4.0.1 → winrt_runtime-4.0.3}/src/types.h +0 -0
|
@@ -184,11 +184,8 @@ namespace py::cpp::_winrt
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
auto const& guid = *static_cast<winrt::guid const*>(info->guid);
|
|
187
|
-
auto const
|
|
188
|
-
|
|
189
|
-
py::winrt_wrapper<winrt::Windows::Foundation::IUnknown>*>(obj)
|
|
190
|
-
->obj;
|
|
191
|
-
if (!instance)
|
|
187
|
+
auto const abi = py::interp::held_abi(obj);
|
|
188
|
+
if (!abi)
|
|
192
189
|
{
|
|
193
190
|
Py_RETURN_FALSE;
|
|
194
191
|
}
|
|
@@ -201,7 +198,8 @@ namespace py::cpp::_winrt
|
|
|
201
198
|
|
|
202
199
|
{
|
|
203
200
|
auto _gil = py::release_gil();
|
|
204
|
-
hr =
|
|
201
|
+
hr = static_cast<::IUnknown*>(abi)->QueryInterface(
|
|
202
|
+
guid, queried.put_void());
|
|
205
203
|
queried = nullptr;
|
|
206
204
|
}
|
|
207
205
|
|
|
@@ -322,9 +320,32 @@ namespace py::cpp::_winrt
|
|
|
322
320
|
nullptr},
|
|
323
321
|
{}};
|
|
324
322
|
|
|
323
|
+
/**
|
|
324
|
+
* __call__ of every projected class: what type's does, and then, for a
|
|
325
|
+
* Python class derived from a composable one whose __init__() returned
|
|
326
|
+
* without composing the instance, composing it with the call's arguments.
|
|
327
|
+
*/
|
|
328
|
+
static PyObject* Object_Static_call(
|
|
329
|
+
PyObject* type, PyObject* args, PyObject* kwds) noexcept
|
|
330
|
+
{
|
|
331
|
+
py::pyobj_handle self{PyType_Type.tp_call(type, args, kwds)};
|
|
332
|
+
if (!self)
|
|
333
|
+
{
|
|
334
|
+
return nullptr;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (!py::interp::compose_after_init(self.get(), args, kwds))
|
|
338
|
+
{
|
|
339
|
+
return nullptr;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return self.detach();
|
|
343
|
+
}
|
|
344
|
+
|
|
325
345
|
static PyType_Slot Object_Static_type_slots[]
|
|
326
346
|
= {{Py_tp_base, reinterpret_cast<void*>(&PyType_Type)},
|
|
327
347
|
{Py_tp_methods, reinterpret_cast<void*>(Object_Static_methods)},
|
|
348
|
+
{Py_tp_call, reinterpret_cast<void*>(Object_Static_call)},
|
|
328
349
|
{}};
|
|
329
350
|
|
|
330
351
|
static PyType_Spec Object_Static_type_spec
|
|
@@ -377,6 +398,11 @@ namespace py::cpp::_winrt
|
|
|
377
398
|
py::winrt_wrapper<winrt::Windows::Foundation::IInspectable>* self,
|
|
378
399
|
void* /*unused*/) noexcept
|
|
379
400
|
{
|
|
401
|
+
if (!py::interp::instance_abi(reinterpret_cast<PyObject*>(self)))
|
|
402
|
+
{
|
|
403
|
+
return nullptr;
|
|
404
|
+
}
|
|
405
|
+
|
|
380
406
|
return py::interp::iids_of(self->obj);
|
|
381
407
|
}
|
|
382
408
|
|
|
@@ -388,6 +414,11 @@ namespace py::cpp::_winrt
|
|
|
388
414
|
py::winrt_wrapper<winrt::Windows::Foundation::IInspectable>* self,
|
|
389
415
|
void* /*unused*/) noexcept
|
|
390
416
|
{
|
|
417
|
+
if (!py::interp::instance_abi(reinterpret_cast<PyObject*>(self)))
|
|
418
|
+
{
|
|
419
|
+
return nullptr;
|
|
420
|
+
}
|
|
421
|
+
|
|
391
422
|
return py::interp::runtime_class_name_of(self->obj);
|
|
392
423
|
}
|
|
393
424
|
|
|
@@ -470,6 +501,13 @@ namespace py::cpp::_winrt
|
|
|
470
501
|
Py_RETURN_NOTIMPLEMENTED;
|
|
471
502
|
}
|
|
472
503
|
|
|
504
|
+
// A Python object derived from a composable class holds nothing until
|
|
505
|
+
// its __init__() has composed it, and is no other object until then.
|
|
506
|
+
if (!py::interp::held_abi(reinterpret_cast<PyObject*>(self)))
|
|
507
|
+
{
|
|
508
|
+
Py_RETURN_NOTIMPLEMENTED;
|
|
509
|
+
}
|
|
510
|
+
|
|
473
511
|
auto const equal
|
|
474
512
|
= self->obj
|
|
475
513
|
== reinterpret_cast<
|
|
@@ -482,6 +520,14 @@ namespace py::cpp::_winrt
|
|
|
482
520
|
static Py_hash_t Object_hash(
|
|
483
521
|
py::winrt_wrapper<winrt::Windows::Foundation::IInspectable>* self) noexcept
|
|
484
522
|
{
|
|
523
|
+
// A Python object derived from a composable class holds nothing until
|
|
524
|
+
// its __init__() has composed it, and hashing it then would give a
|
|
525
|
+
// hash that changes when it is composed.
|
|
526
|
+
if (!py::interp::instance_abi(reinterpret_cast<PyObject*>(self)))
|
|
527
|
+
{
|
|
528
|
+
return -1;
|
|
529
|
+
}
|
|
530
|
+
|
|
485
531
|
return static_cast<Py_hash_t>(
|
|
486
532
|
std::hash<winrt::Windows::Foundation::IInspectable>{}(self->obj));
|
|
487
533
|
}
|
|
@@ -923,21 +923,23 @@ namespace py::interp
|
|
|
923
923
|
}
|
|
924
924
|
|
|
925
925
|
/**
|
|
926
|
-
*
|
|
927
|
-
*
|
|
928
|
-
* composed into, each holding the other.
|
|
926
|
+
* Composes @p self, which this thread has claimed by storing composing_abi
|
|
927
|
+
* in it, into a WinRT object: the Python object, and the WinRT object it
|
|
928
|
+
* is composed into, each holding the other.
|
|
929
929
|
*
|
|
930
|
-
* @returns
|
|
931
|
-
* Python error set.
|
|
930
|
+
* @returns @c true with @p self holding the WinRT object, or @c false with
|
|
931
|
+
* a Python error set and @p self still holding composing_abi.
|
|
932
932
|
*/
|
|
933
|
-
|
|
934
|
-
|
|
933
|
+
bool compose_claimed(
|
|
934
|
+
PyObject* self,
|
|
935
935
|
type_entry& entry,
|
|
936
936
|
member_desc const& constructor,
|
|
937
937
|
overload_desc& overload,
|
|
938
938
|
PyObject* const* args,
|
|
939
939
|
Py_ssize_t nargs) noexcept
|
|
940
940
|
{
|
|
941
|
+
auto* const type = Py_TYPE(self);
|
|
942
|
+
|
|
941
943
|
if (!composes(overload))
|
|
942
944
|
{
|
|
943
945
|
PyErr_Format(
|
|
@@ -946,14 +948,14 @@ namespace py::interp
|
|
|
946
948
|
"instance rather than composing one",
|
|
947
949
|
entry.winrt_name,
|
|
948
950
|
overload.winrt_name);
|
|
949
|
-
return
|
|
951
|
+
return false;
|
|
950
952
|
}
|
|
951
953
|
|
|
952
954
|
// init_subclass() refuses such a class already, unless a base before
|
|
953
955
|
// it in the MRO does not call the next __init_subclass__().
|
|
954
956
|
if (!check_composed_bases(type))
|
|
955
957
|
{
|
|
956
|
-
return
|
|
958
|
+
return false;
|
|
957
959
|
}
|
|
958
960
|
|
|
959
961
|
// What the outer object answers itself: every interface the Python
|
|
@@ -963,14 +965,14 @@ namespace py::interp
|
|
|
963
965
|
|
|
964
966
|
if (!collect_interfaces(type, interfaces))
|
|
965
967
|
{
|
|
966
|
-
return
|
|
968
|
+
return false;
|
|
967
969
|
}
|
|
968
970
|
|
|
969
971
|
for (auto* const iface : interfaces)
|
|
970
972
|
{
|
|
971
973
|
if (!ensure_interface_vtable(*iface))
|
|
972
974
|
{
|
|
973
|
-
return
|
|
975
|
+
return false;
|
|
974
976
|
}
|
|
975
977
|
}
|
|
976
978
|
|
|
@@ -1003,14 +1005,14 @@ namespace py::interp
|
|
|
1003
1005
|
auto* const iface = ensure_named_entry(*base->owner, overridables[i]);
|
|
1004
1006
|
if (!iface)
|
|
1005
1007
|
{
|
|
1006
|
-
return
|
|
1008
|
+
return false;
|
|
1007
1009
|
}
|
|
1008
1010
|
|
|
1009
1011
|
// An overridable interface is exclusive to the class, so the
|
|
1010
1012
|
// class's own record is where its members are written down.
|
|
1011
1013
|
if (!ensure_interface_vtable(*iface, *base))
|
|
1012
1014
|
{
|
|
1013
|
-
return
|
|
1015
|
+
return false;
|
|
1014
1016
|
}
|
|
1015
1017
|
|
|
1016
1018
|
if (!named)
|
|
@@ -1026,16 +1028,10 @@ namespace py::interp
|
|
|
1026
1028
|
}
|
|
1027
1029
|
}
|
|
1028
1030
|
|
|
1029
|
-
pyobj_handle self{type->tp_alloc(type, 0)};
|
|
1030
|
-
if (!self)
|
|
1031
|
-
{
|
|
1032
|
-
return nullptr;
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
1031
|
// A weak reference to the pair takes the Python object from whatever
|
|
1036
1032
|
// thread resolves it, which a free-threaded build only allows for an
|
|
1037
1033
|
// object that has been told to expect it.
|
|
1038
|
-
PyUnstable_EnableTryIncRef(self
|
|
1034
|
+
PyUnstable_EnableTryIncRef(self);
|
|
1039
1035
|
|
|
1040
1036
|
auto outer = std::make_unique<compose_object>();
|
|
1041
1037
|
|
|
@@ -1047,7 +1043,7 @@ namespace py::interp
|
|
|
1047
1043
|
outer->source_head.target = outer.get();
|
|
1048
1044
|
outer->weak_head.vtable = weak_reference_vtable;
|
|
1049
1045
|
outer->weak_head.target = outer.get();
|
|
1050
|
-
outer->calls.obj = self
|
|
1046
|
+
outer->calls.obj = self;
|
|
1051
1047
|
|
|
1052
1048
|
try
|
|
1053
1049
|
{
|
|
@@ -1056,7 +1052,7 @@ namespace py::interp
|
|
|
1056
1052
|
catch (...)
|
|
1057
1053
|
{
|
|
1058
1054
|
to_PyErr();
|
|
1059
|
-
return
|
|
1055
|
+
return false;
|
|
1060
1056
|
}
|
|
1061
1057
|
|
|
1062
1058
|
make_tearoffs(interfaces, outer->head, outer->calls, outer->tearoffs);
|
|
@@ -1074,7 +1070,7 @@ namespace py::interp
|
|
|
1074
1070
|
if (!instance)
|
|
1075
1071
|
{
|
|
1076
1072
|
object_release(&outer.release()->head);
|
|
1077
|
-
return
|
|
1073
|
+
return false;
|
|
1078
1074
|
}
|
|
1079
1075
|
|
|
1080
1076
|
// The wrapper holds the outer object seen as the class's own default
|
|
@@ -1098,12 +1094,50 @@ namespace py::interp
|
|
|
1098
1094
|
catch (...)
|
|
1099
1095
|
{
|
|
1100
1096
|
to_PyErr();
|
|
1101
|
-
return
|
|
1097
|
+
return false;
|
|
1102
1098
|
}
|
|
1103
1099
|
}
|
|
1104
1100
|
|
|
1105
|
-
abi_of(self
|
|
1101
|
+
abi_of(self) = abi;
|
|
1102
|
+
|
|
1103
|
+
return true;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Composes @p self, an instance of a Python class derived from the
|
|
1108
|
+
* composable class @p entry that holds nothing yet, into a WinRT object.
|
|
1109
|
+
*
|
|
1110
|
+
* The constructor is a call into WinRT, which another thread can run
|
|
1111
|
+
* during, so the thread that composes claims @p self first, by storing
|
|
1112
|
+
* composing_abi in it, and a second thread's claim fails as a composition
|
|
1113
|
+
* of an object that is composed already.
|
|
1114
|
+
*
|
|
1115
|
+
* @returns @c true, or @c false with a Python error set and @p self left
|
|
1116
|
+
* holding nothing.
|
|
1117
|
+
*/
|
|
1118
|
+
bool compose_into(
|
|
1119
|
+
PyObject* self,
|
|
1120
|
+
type_entry& entry,
|
|
1121
|
+
member_desc const& constructor,
|
|
1122
|
+
overload_desc& overload,
|
|
1123
|
+
PyObject* const* args,
|
|
1124
|
+
Py_ssize_t nargs) noexcept
|
|
1125
|
+
{
|
|
1126
|
+
void* expected{};
|
|
1127
|
+
|
|
1128
|
+
if (!std::atomic_ref<void*>{abi_of(self)}.compare_exchange_strong(
|
|
1129
|
+
expected, composing_abi))
|
|
1130
|
+
{
|
|
1131
|
+
set_already_composed_error(self);
|
|
1132
|
+
return false;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
if (!compose_claimed(self, entry, constructor, overload, args, nargs))
|
|
1136
|
+
{
|
|
1137
|
+
abi_of(self) = nullptr;
|
|
1138
|
+
return false;
|
|
1139
|
+
}
|
|
1106
1140
|
|
|
1107
|
-
return
|
|
1141
|
+
return true;
|
|
1108
1142
|
}
|
|
1109
1143
|
} // namespace py::interp
|
|
@@ -142,10 +142,16 @@ namespace py::interp
|
|
|
142
142
|
return nullptr;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
auto const abi = instance_abi(self);
|
|
146
|
+
if (!abi)
|
|
147
|
+
{
|
|
148
|
+
return nullptr;
|
|
149
|
+
}
|
|
150
|
+
|
|
145
151
|
return call_member(
|
|
146
152
|
info->members[0],
|
|
147
153
|
*overload,
|
|
148
|
-
|
|
154
|
+
abi,
|
|
149
155
|
nargs == 0 ? nullptr : &PyTuple_GET_ITEM(args, 0),
|
|
150
156
|
nargs);
|
|
151
157
|
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// The part of handles.h that is not inline: the thread states of threads
|
|
2
|
+
// Python has not seen.
|
|
3
|
+
//
|
|
4
|
+
// WinRT calls back on threads of its own: the thread pool, the thread of a
|
|
5
|
+
// DispatcherQueue made with CreateOnDedicatedThread(), an AudioGraph's audio
|
|
6
|
+
// thread. Attaching from such a thread creates a thread state for it, and the
|
|
7
|
+
// matching release deletes it again, so on its own whatever Python keeps per
|
|
8
|
+
// thread state would last for one callback: a threading.local, the running
|
|
9
|
+
// asyncio loop, the contextvars context. It would also cost a thread state
|
|
10
|
+
// made and cleared on every callback.
|
|
11
|
+
//
|
|
12
|
+
// So the first attach on such a thread makes the thread state with
|
|
13
|
+
// PyGILState_Ensure() and keeps that count of it, and every attach after finds
|
|
14
|
+
// it and reuses it. The count is given back when the thread exits, from a
|
|
15
|
+
// fiber-local storage callback, and the last release clears and deletes the
|
|
16
|
+
// thread state as it would have: nothing is left behind. Unlike a C++
|
|
17
|
+
// thread_local destructor or DLL_THREAD_DETACH, Windows calls FLS callbacks on
|
|
18
|
+
// the exiting thread before it takes the loader lock, so clearing the thread
|
|
19
|
+
// state there, which can run any finalizer, is safe.
|
|
20
|
+
//
|
|
21
|
+
// The thread state is made by PyGILState_Ensure() rather than by
|
|
22
|
+
// PyThreadState_Ensure*() even from 3.15, because a thread state made that way
|
|
23
|
+
// is deleted when its count runs out, and PyThreadState_EnsureFromView()
|
|
24
|
+
// would hold an interpreter guard for as long as the count stayed up, which
|
|
25
|
+
// keeps the interpreter from ever finalizing. PyThreadState_Ensure*() reuses
|
|
26
|
+
// the thread state PyGILState_Ensure() bound to the thread, and lets go of
|
|
27
|
+
// its guard each time.
|
|
28
|
+
|
|
29
|
+
#ifndef NOMINMAX
|
|
30
|
+
#define NOMINMAX
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
#include <Windows.h>
|
|
34
|
+
|
|
35
|
+
#include <pywinrt/handles.h>
|
|
36
|
+
|
|
37
|
+
namespace
|
|
38
|
+
{
|
|
39
|
+
/**
|
|
40
|
+
* Gives back the count keep_thread_state() kept, on the thread that is
|
|
41
|
+
* exiting; the release that takes the count to zero clears and deletes
|
|
42
|
+
* the thread state.
|
|
43
|
+
*/
|
|
44
|
+
void NTAPI on_thread_exit(void*) noexcept
|
|
45
|
+
{
|
|
46
|
+
#if PY_VERSION_HEX >= 0x030F0000
|
|
47
|
+
PyInterpreterView* const view = py::main_interpreter_view();
|
|
48
|
+
PyInterpreterGuard* const guard
|
|
49
|
+
= view ? PyInterpreterGuard_FromView(view) : nullptr;
|
|
50
|
+
|
|
51
|
+
// Without a guard, the interpreter is finalizing or gone, and deletes
|
|
52
|
+
// the thread states of all its threads itself.
|
|
53
|
+
if (!guard)
|
|
54
|
+
{
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
#else
|
|
58
|
+
if (!Py_IsInitialized() || Py_IsFinalizing())
|
|
59
|
+
{
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
#endif
|
|
63
|
+
|
|
64
|
+
// An interpreter initialized again since is not the one the thread
|
|
65
|
+
// state was kept in, and this thread has none in it.
|
|
66
|
+
if (PyGILState_GetThisThreadState())
|
|
67
|
+
{
|
|
68
|
+
PyGILState_STATE const state = PyGILState_Ensure();
|
|
69
|
+
// The kept count; the GIL stays held for the release below.
|
|
70
|
+
PyGILState_Release(PyGILState_LOCKED);
|
|
71
|
+
PyGILState_Release(state);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#if PY_VERSION_HEX >= 0x030F0000
|
|
75
|
+
PyInterpreterGuard_Close(guard);
|
|
76
|
+
#endif
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The FLS slot whose callback gives the thread state back, or
|
|
81
|
+
* FLS_OUT_OF_INDEXES. It is never freed: FlsFree() would call the callback
|
|
82
|
+
* for every thread at once, on the thread that frees it, and the module is
|
|
83
|
+
* never unloaded.
|
|
84
|
+
*/
|
|
85
|
+
DWORD fls_index() noexcept
|
|
86
|
+
{
|
|
87
|
+
static DWORD const index = FlsAlloc(on_thread_exit);
|
|
88
|
+
return index;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Any value but null, which FLS takes to mean "nothing to clean up".
|
|
93
|
+
*/
|
|
94
|
+
void* const kept = reinterpret_cast<void*>(1);
|
|
95
|
+
} // namespace
|
|
96
|
+
|
|
97
|
+
namespace py
|
|
98
|
+
{
|
|
99
|
+
#if PY_VERSION_HEX >= 0x030F0000
|
|
100
|
+
/**
|
|
101
|
+
* The main interpreter, for attaching to it from a thread Python has not
|
|
102
|
+
* seen; @c nullptr if out of memory.
|
|
103
|
+
*/
|
|
104
|
+
PyInterpreterView* main_interpreter_view() noexcept
|
|
105
|
+
{
|
|
106
|
+
// A view does not keep the interpreter from finalizing, so the one
|
|
107
|
+
// taken on first use serves for as long as the process runs.
|
|
108
|
+
static PyInterpreterView* const view = PyInterpreterView_FromMain();
|
|
109
|
+
return view;
|
|
110
|
+
}
|
|
111
|
+
#endif
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Gives the calling thread, which has no Python thread state, one that
|
|
115
|
+
* lasts until the thread exits, so that what Python keeps per thread -
|
|
116
|
+
* threading.local, the running asyncio loop, the contextvars context -
|
|
117
|
+
* carries over from one WinRT callback to the next. Without it, the thread
|
|
118
|
+
* state that attaching creates is deleted again when the callback returns.
|
|
119
|
+
* Call it without the GIL and before attaching.
|
|
120
|
+
*/
|
|
121
|
+
void keep_thread_state() noexcept
|
|
122
|
+
{
|
|
123
|
+
DWORD const index = fls_index();
|
|
124
|
+
|
|
125
|
+
if (index == FLS_OUT_OF_INDEXES)
|
|
126
|
+
{
|
|
127
|
+
return; // each callback makes its own thread state
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
#if PY_VERSION_HEX >= 0x030F0000
|
|
131
|
+
PyInterpreterView* const view = main_interpreter_view();
|
|
132
|
+
PyInterpreterGuard* const guard
|
|
133
|
+
= view ? PyInterpreterGuard_FromView(view) : nullptr;
|
|
134
|
+
|
|
135
|
+
if (!guard)
|
|
136
|
+
{
|
|
137
|
+
return; // finalizing: the attach that follows fails too
|
|
138
|
+
}
|
|
139
|
+
#endif
|
|
140
|
+
|
|
141
|
+
// Makes the thread state, binds it to the thread and attaches it.
|
|
142
|
+
PyGILState_STATE const state = PyGILState_Ensure();
|
|
143
|
+
|
|
144
|
+
if (FlsSetValue(index, kept))
|
|
145
|
+
{
|
|
146
|
+
// Detaches, keeping the count.
|
|
147
|
+
PyEval_SaveThread();
|
|
148
|
+
}
|
|
149
|
+
else
|
|
150
|
+
{
|
|
151
|
+
// Deletes the thread state again.
|
|
152
|
+
PyGILState_Release(state);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
#if PY_VERSION_HEX >= 0x030F0000
|
|
156
|
+
PyInterpreterGuard_Close(guard);
|
|
157
|
+
#endif
|
|
158
|
+
}
|
|
159
|
+
} // namespace py
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
namespace py
|
|
12
12
|
{
|
|
13
|
+
#if PY_VERSION_HEX >= 0x030F0000
|
|
14
|
+
PyInterpreterView* main_interpreter_view() noexcept;
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
void keep_thread_state() noexcept;
|
|
18
|
+
|
|
13
19
|
/**
|
|
14
20
|
* Holds the Python GIL for as long as it is in scope, unless the
|
|
15
21
|
* interpreter is being finalized or already has been, in which case it
|
|
@@ -27,7 +33,15 @@ namespace py
|
|
|
27
33
|
* From Python 3.15, PyThreadState_EnsureFromView() (PEP 788) makes the
|
|
28
34
|
* check and the attach one step. Before that they are two, so a thread
|
|
29
35
|
* that passes the check just as another starts finalizing still attaches
|
|
30
|
-
* to an interpreter that is going away.
|
|
36
|
+
* to an interpreter that is going away. on_thread_exit() in handles.cpp
|
|
37
|
+
* takes the same two steps on a thread that is exiting, inside
|
|
38
|
+
* LdrShutdownThread(), where the attach then hangs the thread (3.14) or
|
|
39
|
+
* re-enters thread exit (3.12, 3.13). That needs finalization to start
|
|
40
|
+
* during the thread's exit, a window of milliseconds.
|
|
41
|
+
*
|
|
42
|
+
* On a thread Python has not seen, which is most threads WinRT calls back
|
|
43
|
+
* on, the guard first gives the thread a thread state of its own: see
|
|
44
|
+
* keep_thread_state().
|
|
31
45
|
*/
|
|
32
46
|
struct gil_guard
|
|
33
47
|
{
|
|
@@ -55,15 +69,18 @@ namespace py
|
|
|
55
69
|
private:
|
|
56
70
|
static PyThreadStateToken* attach() noexcept
|
|
57
71
|
{
|
|
58
|
-
|
|
59
|
-
// taken on first use serves for as long as the process runs.
|
|
60
|
-
static PyInterpreterView* const view = PyInterpreterView_FromMain();
|
|
72
|
+
PyInterpreterView* const view = main_interpreter_view();
|
|
61
73
|
|
|
62
74
|
if (!view)
|
|
63
75
|
{
|
|
64
76
|
return nullptr;
|
|
65
77
|
}
|
|
66
78
|
|
|
79
|
+
if (!PyGILState_GetThisThreadState())
|
|
80
|
+
{
|
|
81
|
+
keep_thread_state();
|
|
82
|
+
}
|
|
83
|
+
|
|
67
84
|
return PyThreadState_EnsureFromView(view);
|
|
68
85
|
}
|
|
69
86
|
|
|
@@ -80,6 +97,11 @@ namespace py
|
|
|
80
97
|
{
|
|
81
98
|
if (m_held)
|
|
82
99
|
{
|
|
100
|
+
if (!PyGILState_GetThisThreadState())
|
|
101
|
+
{
|
|
102
|
+
keep_thread_state();
|
|
103
|
+
}
|
|
104
|
+
|
|
83
105
|
m_state = PyGILState_Ensure();
|
|
84
106
|
}
|
|
85
107
|
}
|
|
@@ -352,7 +352,7 @@ namespace py::interp
|
|
|
352
352
|
}
|
|
353
353
|
|
|
354
354
|
winrt::Windows::Foundation::IUnknown object;
|
|
355
|
-
winrt::copy_from_abi(object,
|
|
355
|
+
winrt::copy_from_abi(object, held_abi(value));
|
|
356
356
|
if (!object)
|
|
357
357
|
{
|
|
358
358
|
// The conversion says the object holds nothing.
|
|
@@ -82,18 +82,19 @@ namespace py::interp
|
|
|
82
82
|
return nullptr;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
void* abi{};
|
|
86
|
+
if (!self->member->is_static && !(abi = instance_abi(instance)))
|
|
87
|
+
{
|
|
88
|
+
return nullptr;
|
|
89
|
+
}
|
|
90
|
+
|
|
85
91
|
auto const overload = select_overload(*self->member, nargs - 1);
|
|
86
92
|
if (!overload)
|
|
87
93
|
{
|
|
88
94
|
return nullptr;
|
|
89
95
|
}
|
|
90
96
|
|
|
91
|
-
return call_member(
|
|
92
|
-
*self->member,
|
|
93
|
-
*overload,
|
|
94
|
-
self->member->is_static ? nullptr : abi_of(instance),
|
|
95
|
-
args + 1,
|
|
96
|
-
nargs - 1);
|
|
97
|
+
return call_member(*self->member, *overload, abi, args + 1, nargs - 1);
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
PyObject* method_descr_get(
|
|
@@ -211,18 +212,20 @@ namespace py::interp
|
|
|
211
212
|
PyObject* property_get(PyObject* self, void* closure) noexcept
|
|
212
213
|
{
|
|
213
214
|
auto const member = static_cast<member_desc*>(closure);
|
|
215
|
+
|
|
216
|
+
void* abi{};
|
|
217
|
+
if (!member->is_static && !(abi = instance_abi(self)))
|
|
218
|
+
{
|
|
219
|
+
return nullptr;
|
|
220
|
+
}
|
|
221
|
+
|
|
214
222
|
auto const overload = select_overload(*member, 0);
|
|
215
223
|
if (!overload)
|
|
216
224
|
{
|
|
217
225
|
return nullptr;
|
|
218
226
|
}
|
|
219
227
|
|
|
220
|
-
return call_member(
|
|
221
|
-
*member,
|
|
222
|
-
*overload,
|
|
223
|
-
member->is_static ? nullptr : abi_of(self),
|
|
224
|
-
nullptr,
|
|
225
|
-
0);
|
|
228
|
+
return call_member(*member, *overload, abi, nullptr, 0);
|
|
226
229
|
}
|
|
227
230
|
|
|
228
231
|
int property_set(PyObject* self, PyObject* value, void* closure) noexcept
|
|
@@ -236,18 +239,19 @@ namespace py::interp
|
|
|
236
239
|
return -1;
|
|
237
240
|
}
|
|
238
241
|
|
|
242
|
+
void* abi{};
|
|
243
|
+
if (!member->is_static && !(abi = instance_abi(self)))
|
|
244
|
+
{
|
|
245
|
+
return -1;
|
|
246
|
+
}
|
|
247
|
+
|
|
239
248
|
auto const overload = select_overload(*member, 1);
|
|
240
249
|
if (!overload)
|
|
241
250
|
{
|
|
242
251
|
return -1;
|
|
243
252
|
}
|
|
244
253
|
|
|
245
|
-
pyobj_handle result{call_member(
|
|
246
|
-
*member,
|
|
247
|
-
*overload,
|
|
248
|
-
member->is_static ? nullptr : abi_of(self),
|
|
249
|
-
&value,
|
|
250
|
-
1)};
|
|
254
|
+
pyobj_handle result{call_member(*member, *overload, abi, &value, 1)};
|
|
251
255
|
|
|
252
256
|
return result ? 0 : -1;
|
|
253
257
|
}
|