Commit 9e47afe4 authored by Simon Feltman's avatar Simon Feltman
Browse files

Unify Python object to GValue GI marshaling code

Add pygi_marshal_from_py_g_value which can be used for direct gi method
call args and vfunc out args. The new method also adds an "is_allocated"
parameter that will be used to fix leaks in the future.

https://bugzilla.gnome.org/show_bug.cgi?id=693405
parent 15cd7be5
......@@ -1239,41 +1239,18 @@ 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;
......
......@@ -1652,30 +1652,9 @@ _pygi_marshal_from_py_interface_struct (PyGIInvokeState *state,
arg->v_pointer = closure;
return TRUE;
} else if (iface_cache->g_type == G_TYPE_VALUE) {
GValue *value;
GType object_type;
object_type = pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
if (object_type == G_TYPE_INVALID) {
PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
return FALSE;
}
/* if already a gvalue, use that, else marshal into gvalue */
if (object_type == G_TYPE_VALUE) {
value = (GValue *)( (PyGObject *)py_arg)->obj;
} else {
value = g_slice_new0 (GValue);
g_value_init (value, object_type);
if (pyg_value_from_pyobject (value, py_arg) < 0) {
g_slice_free (GValue, value);
PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
return FALSE;
}
}
arg->v_pointer = value;
return TRUE;
return pygi_marshal_from_py_gvalue(py_arg, arg,
arg_cache->transfer,
arg_cache->is_caller_allocates);
} else if (iface_cache->is_foreign) {
PyObject *success;
success = pygi_struct_foreign_convert_to_g_argument (py_arg,
......@@ -1910,3 +1889,50 @@ pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
arg->v_pointer = gobj;
return TRUE;
}
/* pygi_marshal_from_py_gvalue:
* py_arg: (in):
* arg: (out):
* transfer:
* is_allocated: TRUE if arg->v_pointer is an already allocated GValue
*/
gboolean
pygi_marshal_from_py_gvalue (PyObject *py_arg,
GIArgument *arg,
GITransfer transfer,
gboolean is_allocated) {
GValue *value;
GType object_type;
object_type = pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
if (object_type == G_TYPE_INVALID) {
PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
return FALSE;
}
if (is_allocated)
value = (GValue *)arg->v_pointer;
else
value = g_slice_new0 (GValue);
/* if already a gvalue, use that, else marshal into gvalue */
if (object_type == G_TYPE_VALUE) {
GValue *source_value = pyg_boxed_get (py_arg, GValue);
if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
g_value_init (value, G_VALUE_TYPE (source_value));
g_value_copy (source_value, value);
} else {
if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
g_value_init (value, object_type);
if (pyg_value_from_pyobject (value, py_arg) < 0) {
if (!is_allocated)
g_slice_free (GValue, value);
PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
return FALSE;
}
}
arg->v_pointer = value;
return TRUE;
}
......@@ -190,6 +190,11 @@ gboolean pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
GIArgument *arg, /*out*/
GITransfer transfer);
gboolean pygi_marshal_from_py_gvalue (PyObject *py_arg, /*in*/
GIArgument *arg, /*out*/
GITransfer transfer,
gboolean is_allocated);
G_END_DECLS
#endif /* __PYGI_MARSHAL_from_py_PY__ */
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