diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-02-01 12:32:28 +0100 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-03-05 15:50:44 +0100 |
| commit | d8910df3ccea2897f5e228058f17176cb1fe4093 (patch) | |
| tree | 1dfe36ca093e05cafd1ae6718e56f2c97ca0278e /sources/pyside6/PySide6/glue/qtnetwork.cpp | |
| parent | 546548acc550e716ec82551c30108eabab87f740 (diff) | |
Long live PyObjectHolder
Add a class PyObjectHolder for passing around Python objects in C++.
It is mainly intended for callables. There are some cases in which
callables are invoked several times or not at all.
The usual construct of passing a lambda which decrefs the callable
after the invocation only works in the case when there is exactly one
single shot invocation. Otherwise, the callable leaks if there is no
invocation or a crash occurs on multiple invocation due to repeated
decref.
To fix this, introduce a class PyObjectHolder which holds a PyObject
with a reference and implements move/copy semantics as well as
destruction with the GIL held. It serves as a base class for functors
which implement a call operator for the invocation.
For the singleshot case, release() can be called after the invocation
as not to unnecessarily delay the release.
Port over the known cases where multiple invocation is documented to
occur to use it.
Change-Id: I2f4c7d497d4be8e48946f77a5a40dc9712dc05dd
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/pyside6/PySide6/glue/qtnetwork.cpp')
| -rw-r--r-- | sources/pyside6/PySide6/glue/qtnetwork.cpp | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/sources/pyside6/PySide6/glue/qtnetwork.cpp b/sources/pyside6/PySide6/glue/qtnetwork.cpp index 4e021711d..f635f4671 100644 --- a/sources/pyside6/PySide6/glue/qtnetwork.cpp +++ b/sources/pyside6/PySide6/glue/qtnetwork.cpp @@ -15,20 +15,28 @@ PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[QHostAddress](ha)); PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[quint16](port)); // @snippet qudpsocket-readdatagram -// @snippet qhostinfo-lookuphost-callable -auto *callable = %PYARG_2; -auto cppCallback = [callable](const QHostInfo &hostInfo) +// @snippet qhostinfo-lookuphost-functor +struct QHostInfoFunctor : public Shiboken::PyObjectHolder +{ +public: + using Shiboken::PyObjectHolder::PyObjectHolder; + + void operator()(const QHostInfo &hostInfo); +}; + +void QHostInfoFunctor::operator()(const QHostInfo &hostInfo) { Shiboken::GilState state; Shiboken::AutoDecRef arglist(PyTuple_New(1)); auto *pyHostInfo = %CONVERTTOPYTHON[QHostInfo](hostInfo); PyTuple_SET_ITEM(arglist.object(), 0, pyHostInfo); - Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); - Py_DECREF(callable); -}; + Shiboken::AutoDecRef ret(PyObject_CallObject(object(), arglist)); + release(); // single shot +} +// @snippet qhostinfo-lookuphost-functor -Py_INCREF(callable); -%CPPSELF.%FUNCTION_NAME(%1, cppCallback); +// @snippet qhostinfo-lookuphost-callable +%CPPSELF.%FUNCTION_NAME(%1, QHostInfoFunctor(%PYARG_2)); // @snippet qhostinfo-lookuphost-callable // @snippet qipv6address-len |
