[pygobject] Move "from Python" GObject out arg marshaler into specialized function



commit 2339e030e4dc4d93ea770bca380a89f831d56be6
Author: Simon Feltman <sfeltman src gnome org>
Date:   Fri Jul 26 19:33:32 2013 -0700

    Move "from Python" GObject out arg marshaler into specialized function
    
    Move hacks specific to out argument marshaling for vfuncs into a
    a specialized function. This allows standard function call marshaling
    to continue working correctly when there are no extra references
    holding the arguments "foo(SomeObject())". This is currently being
    masked because all GI functions are wrapped by additional layers
    of Python functions. When these layers are removed, it exposes
    bugs introduced by reference counting hacks intended for vfunc
    return arguments.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=704037

 gi/pygi-argument.c        |    2 +-
 gi/pygi-marshal-from-py.c |   37 ++++++++++++++++++++++++++++++-------
 gi/pygi-marshal-from-py.h |    3 +++
 3 files changed, 34 insertions(+), 8 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 27b9dfe..7d8a837 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -1060,7 +1060,7 @@ array_success:
                 case GI_INFO_TYPE_INTERFACE:
                 case GI_INFO_TYPE_OBJECT:
                     /* An error within this call will result in a NULL arg */
-                    _pygi_marshal_from_py_gobject (object, &arg, transfer);
+                    _pygi_marshal_from_py_gobject_out_arg (object, &arg, transfer);
                     break;
 
                 default:
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index 5d38baa..7c28234 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -1648,12 +1648,38 @@ _pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
 
     gobj = pygobject_get (py_arg);
     if (transfer == GI_TRANSFER_EVERYTHING) {
-        /* An easy case of adding a new ref that the caller will take ownership of.
-         * Pythons existing ref to the GObject will be managed normally with the wrapper.
+        /* For transfer everything, add a new ref that the callee will take ownership of.
+         * Pythons existing ref to the GObject will be managed with the PyGObject wrapper.
          */
         g_object_ref (gobj);
+    }
+
+    arg->v_pointer = gobj;
+    return TRUE;
+}
+
+/* _pygi_marshal_from_py_gobject_out_arg:
+ * py_arg: (in):
+ * arg: (out):
+ *
+ * A specialization for marshaling Python GObjects used for out/return values
+ * from a Python implemented vfuncs, signals, or an assignment to a GObject property.
+ */
+gboolean
+_pygi_marshal_from_py_gobject_out_arg (PyObject *py_arg, /*in*/
+                                       GIArgument *arg,  /*out*/
+                                       GITransfer transfer) {
+    GObject *gobj;
+    if (!_pygi_marshal_from_py_gobject (py_arg, arg, transfer)) {
+        return FALSE;
+    }
 
-    } else if (py_arg->ob_refcnt == 1 && gobj->ref_count == 1) {
+    /* HACK: At this point the basic marshaling of the GObject was successful
+     * but we add some special case hacks for vfunc returns due to buggy APIs:
+     * https://bugzilla.gnome.org/show_bug.cgi?id=693393
+     */
+    gobj = arg->v_pointer;
+    if (py_arg->ob_refcnt == 1 && gobj->ref_count == 1) {
         /* If both object ref counts are only 1 at this point (the reference held
          * in a return tuple), we assume the GObject will be free'd before reaching
          * its target and become invalid. So instead of getting invalid object errors
@@ -1662,12 +1688,10 @@ _pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
         g_object_ref (gobj);
 
         if (((PyGObject *)py_arg)->private_flags.flags & PYGOBJECT_GOBJECT_WAS_FLOATING) {
-            /* HACK:
+            /*
              * We want to re-float instances that were floating and the Python
              * wrapper assumed ownership. With the additional caveat that there
              * are not any strong references beyond the return tuple.
-             * This should be removed once the following ticket is fixed:
-             * https://bugzilla.gnome.org/show_bug.cgi?id=693393
              */
             g_object_force_floating (gobj);
 
@@ -1686,7 +1710,6 @@ _pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
         }
     }
 
-    arg->v_pointer = gobj;
     return TRUE;
 }
 
diff --git a/gi/pygi-marshal-from-py.h b/gi/pygi-marshal-from-py.h
index f9f0d0f..9f56a6f 100644
--- a/gi/pygi-marshal-from-py.h
+++ b/gi/pygi-marshal-from-py.h
@@ -123,6 +123,9 @@ gboolean _pygi_marshal_from_py_basic_type_cache_adapter  (PyGIInvokeState   *sta
 gboolean _pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
                                         GIArgument *arg,  /*out*/
                                         GITransfer transfer);
+gboolean _pygi_marshal_from_py_gobject_out_arg (PyObject *py_arg, /*in*/
+                                                GIArgument *arg,  /*out*/
+                                                GITransfer transfer);
 
 gboolean _pygi_marshal_from_py_gvalue (PyObject *py_arg, /*in*/
                                        GIArgument *arg,  /*out*/


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