[pygobject] Fix Python to C marshalling of GValue arrays
- From: Martin Pitt <martinpitt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Fix Python to C marshalling of GValue arrays
- Date: Fri, 16 Mar 2012 11:23:11 +0000 (UTC)
commit d7d28d717e38c0546529b09b8b571a5cc631c5b5
Author: Martin Pitt <martin pitt ubuntu com>
Date: Wed Mar 14 22:52:47 2012 +0100
Fix Python to C marshalling of GValue arrays
For GValues we cannot just copy the GValue memory in
_pygi_marshal_from_py_array(), as the from_py_cleanup() function clears and
releases the GValue and with it its v_pointer. Use g_value_copy() to copy by
value instead.
This uncovered another bug in _pygi_marshal_cleanup_from_py_array(): It always
assumed that C arrays contained pointers, but this is not the case for GValue
arrays: these are actual struct arrays, not struct pointer arrays (cf. their
construction in _pygi_marshal_from_py_array()). Check if an array contains
pointers or values and compute the correct array item pointer for both cases.
Also add a corresponding test case for marshalling GValue arrays from C back to
Python, which works fine.
https://bugzilla.gnome.org/show_bug.cgi?id=672065
gi/pygi-marshal-cleanup.c | 19 ++++++++++++++-----
gi/pygi-marshal-from-py.c | 13 ++++++++++++-
tests/test_gi.py | 8 ++++++++
3 files changed, 34 insertions(+), 6 deletions(-)
---
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
index e65731a..d580161 100644
--- a/gi/pygi-marshal-cleanup.c
+++ b/gi/pygi-marshal-cleanup.c
@@ -336,11 +336,20 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
PyGIMarshalCleanupFunc cleanup_func =
sequence_cache->item_cache->from_py_cleanup;
- for(i = 0; i < len; i++) {
- cleanup_func (state,
- sequence_cache->item_cache,
- (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
- TRUE);
+ for (i = 0; i < len; i++) {
+ gpointer item;
+
+ /* case 1: GPtrArray */
+ if (ptr_array_ != NULL)
+ item = g_ptr_array_index (ptr_array_, i);
+ /* case 2: C array or GArray with object pointers */
+ else if (sequence_cache->item_cache->is_pointer)
+ item = g_array_index (array_, gpointer, i);
+ /* case 3: C array or GArray with simple types or structs */
+ else
+ item = array_->data + i * sequence_cache->item_size;
+
+ cleanup_func (state, sequence_cache->item_cache, item, TRUE);
}
}
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index 1926b35..92cd499 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -839,8 +839,19 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
* since GVariants are opaque hence always passed by ref */
g_assert (item_size == sizeof (item.v_pointer));
g_array_insert_val (array_, i, item.v_pointer);
- } else if (!is_boxed || is_gvalue) {
+ } else if (is_gvalue) {
+ GValue* dest = (GValue*) (array_->data + (i * item_size));
+ memset (dest, 0, item_size);
+ if (item.v_pointer != NULL) {
+ g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
+ g_value_copy ((GValue*) item.v_pointer, dest);
+ }
+
+ if (from_py_cleanup)
+ from_py_cleanup (state, item_arg_cache, item.v_pointer, TRUE);
+ } else if (!is_boxed) {
memcpy (array_->data + (i * item_size), item.v_pointer, item_size);
+
if (from_py_cleanup)
from_py_cleanup (state, item_arg_cache, item.v_pointer, TRUE);
} else {
diff --git a/tests/test_gi.py b/tests/test_gi.py
index be18af5..edbe461 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -1046,6 +1046,14 @@ class TestGValue(unittest.TestCase):
value.set_int(42)
self.assertEquals('42', GIMarshallingTests.gvalue_inout(value))
+ def test_gvalue_flat_array_in(self):
+ # the function already asserts the correct values
+ GIMarshallingTests.gvalue_flat_array([42, "42", True])
+
+ def test_gvalue_flat_array_out(self):
+ values = GIMarshallingTests.return_gvalue_flat_array()
+ self.assertEqual(values, [42, '42', True])
+
class TestGClosure(unittest.TestCase):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]