[pygobject] Prevent passing the user data multiple times to callbacks



commit 3066f3a88103f02c7e22db22efbeb501f4e30d32
Author: Garrett Regier <garrett regier riftio com>
Date:   Wed Jun 3 07:50:37 2015 -0700

    Prevent passing the user data multiple times to callbacks
    
    This can happen when a callback has multiple gpointers.
    Also, store the closure index as it is hopefully more reliable
    than guessing.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=750347

 gi/pygi-cache.c   |   24 ++++++++++++++++++++++++
 gi/pygi-cache.h   |    3 +++
 gi/pygi-closure.c |    8 ++------
 3 files changed, 29 insertions(+), 6 deletions(-)
---
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index ca24517..84cc463 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -489,6 +489,8 @@ _callable_cache_generate_args_cache_real (PyGICallableCache *callable_cache,
     callable_cache->return_cache = return_cache;
     g_base_info_unref (return_info);
 
+    callable_cache->user_data_index = -1;
+
     for (i = 0, arg_index = callable_cache->args_offset;
          arg_index < _pygi_callable_cache_args_len (callable_cache);
          i++, arg_index++) {
@@ -498,7 +500,9 @@ _callable_cache_generate_args_cache_real (PyGICallableCache *callable_cache,
 
         arg_info = g_callable_info_get_arg (callable_info, i);
 
+        /* This only happens when dealing with callbacks */
         if (g_arg_info_get_closure (arg_info) == i) {
+            callable_cache->user_data_index = i;
 
             arg_cache = pygi_arg_cache_alloc ();
             _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
@@ -1116,6 +1120,26 @@ pygi_closure_cache_new (GICallableInfo *info)
         len_arg_cache->meta_type = PYGI_META_ARG_TYPE_PARENT;
     }
 
+    /* Prevent guessing multiple user data arguments.
+     * This is required because some versions of GI
+     * do not recognize user_data/data arguments correctly.
+     */
+    if (callable_cache->user_data_index == -1) {
+        for (i = 0; i < _pygi_callable_cache_args_len (callable_cache); i++) {
+            PyGIArgCache *arg_cache;
+
+            arg_cache = g_ptr_array_index (callable_cache->args_cache, i);
+
+            if (arg_cache->direction == PYGI_DIRECTION_TO_PYTHON &&
+                arg_cache->type_tag == GI_TYPE_TAG_VOID &&
+                arg_cache->is_pointer) {
+
+                callable_cache->user_data_index = i;
+                break;
+            }
+        }
+    }
+
     return closure_cache;
 }
 
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 098f3f1..ad41755 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -170,6 +170,9 @@ struct _PyGICallableCache
     GHashTable *arg_name_hash;
     gboolean throws;
 
+    /* Index of user_data arg passed to a callable. */
+    gssize user_data_index;
+
     /* Index of user_data arg that can eat variable args passed to a callable. */
     gssize user_data_varargs_index;
 
diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c
index 1655499..b239777 100644
--- a/gi/pygi-closure.c
+++ b/gi/pygi-closure.c
@@ -370,17 +370,13 @@ _pygi_closure_convert_arguments (PyGIInvokeState *state,
 
     for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
         PyGIArgCache *arg_cache;
-        PyGIDirection direction;
 
         arg_cache = g_ptr_array_index (cache->args_cache, i);
-        direction = arg_cache->direction;
 
-        if (direction & PYGI_DIRECTION_TO_PYTHON) {
+        if (arg_cache->direction & PYGI_DIRECTION_TO_PYTHON) {
             PyObject *value;
 
-            if (direction == PYGI_DIRECTION_TO_PYTHON &&
-                    arg_cache->type_tag == GI_TYPE_TAG_VOID &&
-                    arg_cache->is_pointer) {
+            if (cache->user_data_index == i) {
                 if (state->user_data == NULL) {
                     /* user_data can be NULL for connect functions which don't accept
                      * user_data or as the default for user_data in the middle of function


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]