summaryrefslogtreecommitdiff
path: root/gi/pygi-argument.c
diff options
context:
space:
mode:
Diffstat (limited to 'gi/pygi-argument.c')
-rw-r--r--gi/pygi-argument.c109
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: