[pygobject] Add support for caller-allocated GArray out arguments



commit e44312139426f51e576ef9e880819542cc224383
Author: Martin Pitt <martinpitt gnome org>
Date:   Mon Dec 17 18:02:15 2012 +0100

    Add support for caller-allocated GArray out arguments
    
    https://bugzilla.gnome.org/show_bug.cgi?id=690041

 gi/pygi-cache.c  |    2 +-
 gi/pygi-invoke.c |   57 +++++++++++++++++++++++++++++------------------------
 tests/test_gi.py |    5 ++-
 3 files changed, 35 insertions(+), 29 deletions(-)
---
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 21dd58f..2a44c02 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -1370,7 +1370,7 @@ _args_cache_generate (GICallableInfo *callable_info,
         type_info = g_arg_info_get_type (arg_info);
         type_tag = g_type_info_get_tag (type_info);
 
-        if (type_tag == GI_TYPE_TAG_INTERFACE)
+        if (type_tag == GI_TYPE_TAG_INTERFACE || type_tag == GI_TYPE_TAG_ARRAY)
             is_caller_allocates = g_arg_info_is_caller_allocates (arg_info);
 
         /* must be an child arg filled in by its owner
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index c0f7179..195a830 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -361,33 +361,38 @@ static gboolean _caller_alloc (PyGIInvokeState *state,
                                gssize arg_count,
                                gssize out_count)
 {
-    PyGIInterfaceCache *iface_cache;
-
-    g_assert (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE);
-
-    iface_cache = (PyGIInterfaceCache *)arg_cache;
-
-    state->out_args[out_count].v_pointer = NULL;
-    state->args[arg_count] = &state->out_args[out_count];
-    if (iface_cache->g_type == G_TYPE_BOXED) {
-        state->args[arg_count]->v_pointer =
-            _pygi_boxed_alloc (iface_cache->interface_info, NULL);
-    } else if (iface_cache->g_type == G_TYPE_VALUE) {
-        state->args[arg_count]->v_pointer = g_slice_new0 (GValue);
-    } else if (iface_cache->is_foreign) {
-        PyObject *foreign_struct =
-            pygi_struct_foreign_convert_from_g_argument (
-                iface_cache->interface_info,
-                NULL);
-
-            pygi_struct_foreign_convert_to_g_argument (foreign_struct,
-                                                       iface_cache->interface_info,
-                                                       GI_TRANSFER_EVERYTHING,
-                                                       state->args[arg_count]);
+    if (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
+        PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+
+        state->out_args[out_count].v_pointer = NULL;
+        state->args[arg_count] = &state->out_args[out_count];
+        if (iface_cache->g_type == G_TYPE_BOXED) {
+            state->args[arg_count]->v_pointer =
+                _pygi_boxed_alloc (iface_cache->interface_info, NULL);
+        } else if (iface_cache->g_type == G_TYPE_VALUE) {
+            state->args[arg_count]->v_pointer = g_slice_new0 (GValue);
+        } else if (iface_cache->is_foreign) {
+            PyObject *foreign_struct =
+                pygi_struct_foreign_convert_from_g_argument (
+                    iface_cache->interface_info,
+                    NULL);
+
+                pygi_struct_foreign_convert_to_g_argument (foreign_struct,
+                                                           iface_cache->interface_info,
+                                                           GI_TRANSFER_EVERYTHING,
+                                                           state->args[arg_count]);
+        } else {
+                gssize size = g_struct_info_get_size(
+                    (GIStructInfo *)iface_cache->interface_info);
+                state->args[arg_count]->v_pointer = g_malloc0 (size);
+        }
+    } else if (arg_cache->type_tag == GI_TYPE_TAG_ARRAY) {
+        PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+
+        state->out_args[out_count].v_pointer = g_array_new (TRUE, TRUE, seq_cache->item_size);
+        state->args[arg_count] = &state->out_args[out_count];
     } else {
-            gssize size = g_struct_info_get_size(
-                (GIStructInfo *)iface_cache->interface_info);
-            state->args[arg_count]->v_pointer = g_malloc0 (size);
+        return FALSE;
     }
 
     if (state->args[arg_count]->v_pointer == NULL)
diff --git a/tests/test_gi.py b/tests/test_gi.py
index e55f57c..7c24351 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -959,8 +959,9 @@ class TestGArray(unittest.TestCase):
     def test_garray_utf8_full_out(self):
         self.assertEqual(['0', '1', '2'], GIMarshallingTests.garray_utf8_full_out())
 
-    # FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=690041
-    def disabled_test_garray_utf8_full_out_caller_allocated(self):
+    @unittest.skipUnless(hasattr(GIMarshallingTests, 'garray_utf8_full_out_caller_allocated'),
+                         'too old gobject-introspection')
+    def test_garray_utf8_full_out_caller_allocated(self):
         self.assertEqual(['0', '1', '2'], GIMarshallingTests.garray_utf8_full_out_caller_allocated())
 
     def test_garray_utf8_none_inout(self):



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]