diff options
Diffstat (limited to 'gi/pygi-argument.c')
-rw-r--r-- | gi/pygi-argument.c | 109 |
1 files changed, 37 insertions, 72 deletions
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index 53e0b5c..3b65246 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -31,6 +31,10 @@ #include <pyglib-python-compat.h> #include <pyglib.h> +#include "pygi-marshal-from-py.h" +#include "pygi-marshal-to-py.h" + + static gboolean gi_argument_to_gssize (GIArgument *arg_in, GITypeTag type_tag, @@ -1235,55 +1239,20 @@ array_success: /* Handle special cases first. */ if (g_type_is_a (type, G_TYPE_VALUE)) { - GValue *value; - GType object_type; - gint retval; - - object_type = pyg_type_from_object_strict ( (PyObject *) object->ob_type, FALSE); - if (object_type == G_TYPE_INVALID) { - PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType"); - break; - } - g_warn_if_fail (transfer == GI_TRANSFER_NOTHING); + /* This will currently leak the GValue that is allocated and + * stashed in arg.v_pointer. Out argument marshaling for caller + * allocated GValues already pass in memory for the GValue. + * Further re-factoring is needed to fix this leak. + * See: https://bugzilla.gnome.org/show_bug.cgi?id=693405 + */ + pygi_marshal_from_py_gvalue (object, + &arg, + transfer, + FALSE /*is_allocated*/); - value = g_slice_new0 (GValue); - - /* if already a gvalue, copy, else marshal into gvalue */ - if (object_type == G_TYPE_VALUE) { - /* src GValue's lifecycle is handled by Python - * so we have to copy it into the destination's - * GValue which is freed during the cleanup of - * invoke. - */ - GValue *src = (GValue *)((PyGObject *) object)->obj; - g_value_init (value, G_VALUE_TYPE (src)); - g_value_copy(src, value); - } else { - g_value_init (value, object_type); - retval = pyg_value_from_pyobject (value, object); - if (retval < 0) { - g_slice_free (GValue, value); - PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed"); - break; - } - } - - arg.v_pointer = value; } else if (g_type_is_a (type, G_TYPE_CLOSURE)) { - GClosure *closure; - - if (pyg_type_from_object_strict (object, FALSE) == G_TYPE_CLOSURE) { - closure = (GClosure *)pyg_boxed_get (object, void); - } else { - closure = pyg_closure_new (object, NULL, NULL); - if (closure == NULL) { - PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed"); - break; - } - } - - arg.v_pointer = closure; + pygi_marshal_from_py_gclosure (object, &arg); } else if (g_struct_info_is_foreign (info)) { pygi_struct_foreign_convert_to_g_argument (object, info, transfer, &arg); } else if (g_type_is_a (type, G_TYPE_BOXED)) { @@ -1329,17 +1298,10 @@ array_success: } case GI_INFO_TYPE_INTERFACE: case GI_INFO_TYPE_OBJECT: - if (object == Py_None) { - arg.v_pointer = NULL; - break; - } - - arg.v_pointer = pygobject_get (object); - if (transfer == GI_TRANSFER_EVERYTHING) { - g_object_ref (arg.v_pointer); - } - + /* An error within this call will result in a NULL arg */ + pygi_marshal_from_py_gobject (object, &arg, transfer); break; + default: g_assert_not_reached(); } @@ -1856,23 +1818,26 @@ _pygi_argument_to_object (GIArgument *arg, } case GI_INFO_TYPE_INTERFACE: case GI_INFO_TYPE_OBJECT: - if (arg->v_pointer == NULL) { - object = Py_None; - Py_INCREF (object); - break; - } - - if (G_IS_PARAM_SPEC (arg->v_pointer)) { - object = pyg_param_spec_new (arg->v_pointer); - break; - } - - /* Only sink incoming objects if the transfer everything. - * See: https://bugzilla.gnome.org/show_bug.cgi?id=675726 + /* HACK: + * The following hack is to work around GTK+ sending signals which + * contain floating widgets in them. This assumes control of how + * references are added by the PyGObject wrapper and avoids the sink + * behavior by explicitly passing GI_TRANSFER_EVERYTHING as the transfer + * mode and then re-forcing the object as floating afterwards. + * + * This can be deleted once the following ticket is fixed: + * https://bugzilla.gnome.org/show_bug.cgi?id=693400 */ - object = pygobject_new_full (arg->v_pointer, - /*sink=*/ transfer == GI_TRANSFER_EVERYTHING, - /*type=*/ NULL); + if (arg->v_pointer && + !G_IS_PARAM_SPEC (arg->v_pointer) && + transfer == GI_TRANSFER_NOTHING && + g_object_is_floating (arg->v_pointer)) { + g_object_ref (arg->v_pointer); + object = pygi_marshal_to_py_object (arg, GI_TRANSFER_EVERYTHING); + g_object_force_floating (arg->v_pointer); + } else { + object = pygi_marshal_to_py_object (arg, transfer); + } break; default: |