[pygobject] Fix marshalling of C arrays with explicit length in signal arguments
- From: Martin Pitt <martinpitt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Fix marshalling of C arrays with explicit length in signal arguments
- Date: Wed, 27 Feb 2013 14:41:07 +0000 (UTC)
commit b6fefd625b843d4fc3dabc456584a2ad27a48c8c
Author: Martin Pitt <martinpitt gnome org>
Date: Wed Feb 27 13:41:55 2013 +0100
Fix marshalling of C arrays with explicit length in signal arguments
We need _pygi_argument_to_array() from both closure marshalling (where we have
the arguments as GIArgument array) and signal closure marshalling (where we
have the arguments in a GValue array). Add an alternative "args_values"
parameter to _pygi_argument_to_array() so that callers can specify one or the
other depending on which type they have available.
This allows us to pass on the full argument list for signal closures, so that
_pygi_argument_to_array() can access the explicit length argument for an
array.
This fixes the GSettings:change-event signal.
https://bugzilla.gnome.org/show_bug.cgi?id=662241
gi/pygi-argument.c | 36 ++++++++++++++++++++++++++++--------
gi/pygi-argument.h | 1 +
gi/pygi-closure.c | 2 +-
gi/pygi-info.c | 4 ++--
gi/pygi-signal-closure.c | 3 ++-
tests/test_gio.py | 18 ++++++++++++++++++
6 files changed, 52 insertions(+), 12 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 3b65246..8dd7842 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -762,8 +762,12 @@ check_number_release:
* _pygi_argument_to_array
* @arg: The argument to convert
* @args: Arguments to method invocation, possibly contaning the array length.
- * Set to NULL if this is not for a method call
- * @callable_info: Info on the callable, if this a method call; otherwise NULL
+ * Set to %NULL if this is not for a method call or @args_values is
+ * specified.
+ * @args_values: GValue Arguments to method invocation, possibly contaning the
+ * array length. Set to %NULL if this is not for a method call or
+ * @args is specified.
+ * @callable_info: Info on the callable, if this a method call; otherwise %NULL
* @type_info: The type info for @arg
* @out_free_array: A return location for a gboolean that indicates whether
* or not the wrapped GArray should be freed
@@ -781,6 +785,7 @@ check_number_release:
GArray *
_pygi_argument_to_array (GIArgument *arg,
GIArgument *args[],
+ const GValue *args_values,
GICallableInfo *callable_info,
GITypeInfo *type_info,
gboolean *out_free_array)
@@ -815,7 +820,7 @@ _pygi_argument_to_array (GIArgument *arg,
GIArgInfo length_arg_info;
GITypeInfo length_type_info;
- if (G_UNLIKELY (args == NULL)) {
+ if (G_UNLIKELY (args == NULL && args_values == NULL)) {
g_critical ("Unable to determine array length for %p",
arg->v_pointer);
g_array = g_array_new (is_zero_terminated, FALSE, item_size);
@@ -828,10 +833,21 @@ _pygi_argument_to_array (GIArgument *arg,
g_assert (callable_info);
g_callable_info_load_arg (callable_info, length_arg_pos, &length_arg_info);
g_arg_info_load_type (&length_arg_info, &length_type_info);
- if (!gi_argument_to_gssize (args[length_arg_pos],
- g_type_info_get_tag (&length_type_info),
- &length))
- return NULL;
+
+ if (args != NULL) {
+ if (!gi_argument_to_gssize (args[length_arg_pos],
+ g_type_info_get_tag (&length_type_info),
+ &length))
+ return NULL;
+ } else {
+ /* get it from args_values */
+ GIArgument length_arg = _pygi_argument_from_g_value (&(args_values[length_arg_pos]),
+ &length_type_info);
+ if (!gi_argument_to_gssize (&length_arg,
+ g_type_info_get_tag (&length_type_info),
+ &length))
+ return NULL;
+ }
}
}
@@ -2047,7 +2063,11 @@ _pygi_argument_from_g_value(const GValue *value,
break;
case GI_TYPE_TAG_ARRAY:
case GI_TYPE_TAG_GHASH:
- arg.v_pointer = g_value_get_boxed (value);
+ if (G_VALUE_HOLDS_BOXED (value))
+ arg.v_pointer = g_value_get_boxed (value);
+ else
+ /* e. g. GSettings::change-event */
+ arg.v_pointer = g_value_get_pointer (value);
break;
case GI_TYPE_TAG_INTERFACE:
{
diff --git a/gi/pygi-argument.h b/gi/pygi-argument.h
index a1420ee..ed88214 100644
--- a/gi/pygi-argument.h
+++ b/gi/pygi-argument.h
@@ -50,6 +50,7 @@ gint _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
GArray* _pygi_argument_to_array (GIArgument *arg,
GIArgument *args[],
+ const GValue *args_values,
GICallableInfo *callable_info,
GITypeInfo *type_info,
gboolean *out_free_array);
diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c
index aa9cb78..f49f8e2 100644
--- a/gi/pygi-closure.c
+++ b/gi/pygi-closure.c
@@ -353,7 +353,7 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
arg = (GIArgument*) g_args[i].v_pointer;
if (g_type_info_get_tag (&arg_type) == GI_TYPE_TAG_ARRAY)
- arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args,
+ arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args, NULL,
callable_info, &arg_type, &free_array);
value = _pygi_argument_to_object (arg, &arg_type, transfer);
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 4d5b9bb..362e7cd 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -1245,7 +1245,7 @@ _wrap_g_constant_info_get_value (PyGIBaseInfo *self)
type_info = g_constant_info_get_type ( (GIConstantInfo *) self->info);
if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY) {
- value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL,
+ value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL, NULL,
type_info, &free_array);
}
@@ -1378,7 +1378,7 @@ _wrap_g_field_info_get_value (PyGIBaseInfo *self,
}
if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) {
- value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL,
+ value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL, NULL,
field_type_info, &free_array);
}
diff --git a/gi/pygi-signal-closure.c b/gi/pygi-signal-closure.c
index 36ea168..6e026de 100644
--- a/gi/pygi-signal-closure.c
+++ b/gi/pygi-signal-closure.c
@@ -141,7 +141,8 @@ pygi_signal_closure_marshal(GClosure *closure,
arg = _pygi_argument_from_g_value(¶m_values[i], &type_info);
if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ARRAY) {
- arg.v_pointer = _pygi_argument_to_array (&arg, NULL, NULL,
+ /* Skip the self argument of param_values */
+ arg.v_pointer = _pygi_argument_to_array (&arg, NULL, param_values + 1, signal_info,
&type_info, &free_array);
}
diff --git a/tests/test_gio.py b/tests/test_gio.py
index 942ee00..57ab013 100644
--- a/tests/test_gio.py
+++ b/tests/test_gio.py
@@ -120,6 +120,24 @@ class TestGSettings(unittest.TestCase):
self.assertEqual(bool(empty), True)
self.assertEqual(empty.keys(), [])
+ def test_change_event(self):
+ changed_log = []
+ change_event_log = []
+
+ def on_changed(settings, key):
+ changed_log.append((settings, key))
+
+ def on_change_event(settings, keys, n_keys):
+ change_event_log.append((settings, keys, n_keys))
+
+ self.settings.connect('changed', on_changed)
+ self.settings.connect('change-event', on_change_event)
+ self.settings['test-string'] = 'Moo'
+ self.assertEqual(changed_log, [(self.settings, 'test-string')])
+ self.assertEqual(change_event_log, [(self.settings,
+ [GLib.quark_from_static_string('test-string')],
+ 1)])
+
class TestGFile(unittest.TestCase):
def setUp(self):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]