[pygobject] Properly allocate boxed structs that are (caller-allocates)



commit caac75a6ed6f671b37e38a78e71b87906a00ac1b
Author: Tomeu Vizoso <tomeu vizoso collabora co uk>
Date:   Fri Jul 30 14:14:16 2010 +0200

    Properly allocate boxed structs that are (caller-allocates)
    
    * gi/pygi-boxed.[hc]: Refactor out the allocation of boxed structs
    * gi/pygi-invoke.c: Don't use g_malloc0 for boxed structs that
      are (caller-allocates)
    * tests/test_overrides.py: Split the TreeView tests
    
    https://bugzilla.gnome.org/show_bug.cgi?id=625653

 gi/pygi-boxed.c         |   50 +++++++++++++++++++++++++++++++----------------
 gi/pygi-boxed.h         |   10 +++++---
 gi/pygi-invoke.c        |   16 +++++---------
 tests/test_overrides.py |   39 +++++++++++++++++------------------
 4 files changed, 64 insertions(+), 51 deletions(-)
---
diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c
index 4903834..66a2585 100644
--- a/gi/pygi-boxed.c
+++ b/gi/pygi-boxed.c
@@ -47,6 +47,37 @@ _boxed_dealloc (PyGIBoxed *self)
     ( (PyGObject *) self)->ob_type->tp_free ( (PyObject *) self);
 }
 
+void *
+_pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
+{
+    gsize size;
+
+    /* FIXME: Remove when bgo#622711 is fixed */
+    if (g_registered_type_info_get_g_type (info) == G_TYPE_VALUE) {
+        size = sizeof (GValue);
+    } else {
+        switch (g_base_info_get_type (info)) {
+            case GI_INFO_TYPE_UNION:
+                size = g_union_info_get_size ( (GIUnionInfo *) info);
+                break;
+            case GI_INFO_TYPE_BOXED:
+            case GI_INFO_TYPE_STRUCT:
+                size = g_struct_info_get_size ( (GIStructInfo *) info);
+                break;
+            default:
+                PyErr_Format (PyExc_TypeError,
+                              "info should be Boxed or Union, not '%d'",
+                              g_base_info_get_type (info));
+                return NULL;
+        }
+    }
+
+    if( size_out != NULL)
+        *size_out = size;
+
+    return g_slice_alloc0 (size);
+}
+
 static PyObject *
 _boxed_new (PyTypeObject *type,
             PyObject     *args,
@@ -55,7 +86,7 @@ _boxed_new (PyTypeObject *type,
     static char *kwlist[] = { NULL };
 
     GIBaseInfo *info;
-    gsize size;
+    gsize size = 0;
     gpointer boxed;
     PyGIBoxed *self = NULL;
 
@@ -71,22 +102,7 @@ _boxed_new (PyTypeObject *type,
         return NULL;
     }
 
-    switch (g_base_info_get_type (info)) {
-        case GI_INFO_TYPE_UNION:
-            size = g_union_info_get_size ( (GIUnionInfo *) info);
-            break;
-        case GI_INFO_TYPE_BOXED:
-        case GI_INFO_TYPE_STRUCT:
-            size = g_struct_info_get_size ( (GIStructInfo *) info);
-            break;
-        default:
-            PyErr_Format (PyExc_TypeError,
-                          "info should be Boxed or Union, not '%d'",
-                          g_base_info_get_type (info));
-            return NULL;
-    }
-
-    boxed = g_slice_alloc0 (size);
+    boxed = _pygi_boxed_alloc (info, &size);
     if (boxed == NULL) {
         PyErr_NoMemory();
         goto out;
diff --git a/gi/pygi-boxed.h b/gi/pygi-boxed.h
index 4f84060..a84ec4e 100644
--- a/gi/pygi-boxed.h
+++ b/gi/pygi-boxed.h
@@ -28,10 +28,12 @@ G_BEGIN_DECLS
 
 extern PyTypeObject PyGIBoxed_Type;
 
-PyObject *
-_pygi_boxed_new (PyTypeObject *type,
-                 gpointer      boxed,
-                 gboolean      free_on_dealloc);
+PyObject * _pygi_boxed_new (PyTypeObject *type,
+                            gpointer      boxed,
+                            gboolean      free_on_dealloc);
+
+void * _pygi_boxed_alloc (GIBaseInfo *info,
+                          gsize *size);
 
 void _pygi_boxed_register_types (PyObject *m);
 
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 4608adb..499378b 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -344,19 +344,15 @@ _prepare_invocation_state (struct invocation_state *state,
                     }
 
                     if (is_caller_allocates) {
-                        gsize size;
-
                         /* if caller allocates only use one level of indirection */
                         state->out_args[out_args_pos].v_pointer = NULL;
                         state->args[i] = &state->out_args[out_args_pos];
-
-                        /* FIXME: Remove when bgo#622711 is fixed */
-                        if (g_registered_type_info_get_g_type (info) == G_TYPE_VALUE)
-                            size = sizeof (GValue);
-                        else
-                            size = g_struct_info_get_size ( (GIStructInfo *) info);
-
-                        state->args[i]->v_pointer = g_malloc0 (size);
+                        if (g_type_is_a (g_registered_type_info_get_g_type (info), G_TYPE_BOXED))
+                            state->args[i]->v_pointer = _pygi_boxed_alloc (info, NULL);
+                        else {
+                            gssize size = g_struct_info_get_size ( (GIStructInfo *) info);
+                            state->args[i]->v_pointer = g_malloc0 (size);
+                        }
                     } else {
                         state->out_args[out_args_pos].v_pointer = &state->out_values[out_args_pos];
                         state->out_values[out_args_pos].v_pointer = NULL;
diff --git a/tests/test_overrides.py b/tests/test_overrides.py
index ad2684f..06aa53b 100644
--- a/tests/test_overrides.py
+++ b/tests/test_overrides.py
@@ -166,31 +166,30 @@ class TestGtk(unittest.TestCase):
         button = dialog.get_widget_for_response (Gtk.ResponseType.CLOSE)
         self.assertEquals(Gtk.STOCK_CLOSE, button.get_label())
 
-    def test_tree_api(self):
+    class TestClass(GObject.GObject):
+        __gtype_name__ = "GIOverrideTreeAPITest"
+
+        def __init__(self, tester, int_value, string_value):
+            super(TestGtk.TestClass, self).__init__()
+            self.tester = tester
+            self.int_value = int_value
+            self.string_value = string_value
+
+        def check(self, int_value, string_value):
+            self.tester.assertEquals(int_value, self.int_value)
+            self.tester.assertEquals(string_value, self.string_value)
+
+    def test_tree_store(self):
         self.assertEquals(Gtk.TreeStore, overrides.Gtk.TreeStore)
         self.assertEquals(Gtk.ListStore, overrides.Gtk.ListStore)
         self.assertEquals(Gtk.TreeModel, overrides.Gtk.TreeModel)
         self.assertEquals(Gtk.TreeViewColumn, overrides.Gtk.TreeViewColumn)
 
-        class TestClass(GObject.GObject):
-            __gtype_name__ = "GIOverrideTreeAPITest"
-
-            def __init__(self, tester, int_value, string_value):
-                super(TestClass, self).__init__()
-                self.tester = tester
-                self.int_value = int_value
-                self.string_value = string_value
-
-            def check(self, int_value, string_value):
-                self.tester.assertEquals(int_value, self.int_value)
-                self.tester.assertEquals(string_value, self.string_value)
-
-        # check TreeStore
-        tree_store = Gtk.TreeStore(int, 'gchararray', TestClass)
+        tree_store = Gtk.TreeStore(int, 'gchararray', TestGtk.TestClass)
         parent = None
         for i in xrange(100):
             label = 'this is child #%d' % i
-            testobj = TestClass(self, i, label)
+            testobj = TestGtk.TestClass(self, i, label)
             parent = tree_store.append(parent, (i, label, testobj))
 
         # len gets the number of children in the root node
@@ -213,11 +212,11 @@ class TestGtk(unittest.TestCase):
 
         self.assertEquals(i, 99)
 
-        # check ListStore
+    def test_list_store(self):
         list_store = Gtk.ListStore(int, str, 'GIOverrideTreeAPITest')
         for i in xrange(100):
             label = 'this is row #%d' % i
-            testobj = TestClass(self, i, label)
+            testobj = TestGtk.TestClass(self, i, label)
             parent = list_store.append((i, label, testobj))
 
         self.assertEquals(len(list_store), 100)
@@ -235,7 +234,7 @@ class TestGtk(unittest.TestCase):
 
         self.assertEquals(i, 99)
 
-        # check to see that we can instantiate a TreeViewColumn
+    def test_tree_view_column(self):
         cell = Gtk.CellRendererText()
         column = Gtk.TreeViewColumn(title='This is just a test',
                                     cell_renderer=cell,



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