Commit 2339e030 authored by Simon Feltman's avatar Simon Feltman
Browse files

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
parent 627c5faa
......@@ -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:
......
......@@ -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;
}
......
......@@ -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*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment