summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Berg <bberg@redhat.com>2020-11-13 00:24:54 +0100
committerBenjamin Berg <benjamin@sipsolutions.net>2022-12-26 15:37:36 +0100
commita837c9d7a2b8abb61f6a2ad404c306b30f32b848 (patch)
treef403c568659c954a32c27b9948463ded7eee4868
parent5e6bc1023e6c8553534b04a34495e9470b06c11f (diff)
downloadpygobject-a837c9d7a2b8abb61f6a2ad404c306b30f32b848.tar.gz
closure: Marshal async callback handler if a default value is passed
Default values will usually not be marshaled, as such, this can be used to flag that the async routine needs marshalling. This is a bit backward in a way, but avoids having to expose the closure information to the rest of the code.
-rw-r--r--gi/pygi-closure.c18
-rw-r--r--gi/pygi-invoke-state-struct.h5
-rw-r--r--gi/pygi-invoke.c2
3 files changed, 25 insertions, 0 deletions
diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c
index 6b3889c7..274d2489 100644
--- a/gi/pygi-closure.c
+++ b/gi/pygi-closure.c
@@ -23,6 +23,7 @@
#include "pygi-invoke.h"
#include "pygi-ccallback.h"
#include "pygi-info.h"
+#include "pygi-async.h"
extern PyObject *_PyGIDefaultArgPlaceholder;
@@ -708,6 +709,23 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
callback_cache = (PyGICallbackCache *)arg_cache;
+ if (py_arg == _PyGIDefaultArgPlaceholder) {
+ /* We need to have an async to "marshal" instead in this case. */
+ if (!state->py_async)
+ return FALSE;
+
+ if (callback_cache->user_data_index <= 0)
+ return FALSE;
+
+ user_data_cache = _pygi_callable_cache_get_arg (callable_cache, (guint)callback_cache->user_data_index);
+
+ Py_INCREF (state->py_async);
+ arg->v_pointer = pygi_async_finish_cb;
+ state->args[user_data_cache->c_arg_index].arg_value.v_pointer = state->py_async;
+
+ return TRUE;
+ }
+
if (callback_cache->user_data_index > 0) {
user_data_cache = _pygi_callable_cache_get_arg (callable_cache, (guint)callback_cache->user_data_index);
if (user_data_cache->py_arg_index < state->n_py_in_args) {
diff --git a/gi/pygi-invoke-state-struct.h b/gi/pygi-invoke-state-struct.h
index dbf4e665..22969bb1 100644
--- a/gi/pygi-invoke-state-struct.h
+++ b/gi/pygi-invoke-state-struct.h
@@ -56,6 +56,11 @@ typedef struct _PyGIInvokeState
gboolean failed;
+ /* An awaitable to return for an async function that was called with
+ * default arguments.
+ */
+ PyObject *py_async;
+
gpointer user_data;
/* Function pointer to call with ffi. */
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 7b822e4b..4239f255 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -24,6 +24,7 @@
#include "pygi-marshal-cleanup.h"
#include "pygi-error.h"
#include "pygi-resulttuple.h"
+#include "pygi-async.h"
#include "pygi-foreign.h"
#include "pygi-boxed.h"
@@ -317,6 +318,7 @@ _invoke_state_clear (PyGIInvokeState *state, PyGIFunctionCache *function_cache)
{
_pygi_invoke_arg_state_free (state);
Py_XDECREF (state->py_in_args);
+ Py_XDECREF (state->py_async);
}
static gboolean