[pygobject] Unify Python object to GValue GI marshaling code
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Unify Python object to GValue GI marshaling code
- Date: Sat, 16 Feb 2013 21:55:13 +0000 (UTC)
commit 9e47afe459df942d9ffc4f71b39f1443976293df
Author: Simon Feltman <sfeltman src gnome org>
Date: Fri Feb 15 20:56:12 2013 -0800
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
gi/pygi-argument.c | 43 ++++++--------------------
gi/pygi-marshal-from-py.c | 74 ++++++++++++++++++++++++++++++--------------
gi/pygi-marshal-from-py.h | 5 +++
3 files changed, 65 insertions(+), 57 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 6d0c0d4..81e2ee7 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -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;
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index 381d656..0f1284e 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -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;
+}
diff --git a/gi/pygi-marshal-from-py.h b/gi/pygi-marshal-from-py.h
index 06ba9a4..11a21c9 100644
--- a/gi/pygi-marshal-from-py.h
+++ b/gi/pygi-marshal-from-py.h
@@ -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__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]