[pygobject] we now assume that C arrays of structs are flat so memcpy them when marshalling



commit 46ba7f04ef3df08e07ddda5c10f0c98bec5fa183
Author: John (J5) Palmieri <johnp redhat com>
Date:   Thu Sep 15 00:08:31 2011 -0400

    we now assume that C arrays of structs are flat so memcpy them when marshalling
    
    * there is no way in GI to tell if a C array is flat or an array of pointers
      so we assume that all arrays of simple structs and gvalues are flat and
      all arrays of objects and boxed structs are pointer arrays.
    * this will be removed once GI gets the ability to annotate level of indirection
      for arrays
    https://bugzilla.gnome.org/show_bug.cgi?id=627236

 gi/pygi-marshal-from-py.c |   35 ++++++++++++++++++++++++++++++++---
 tests/test_gi.py          |   29 +++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 3 deletions(-)
---
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index 0516fe2..6d41eb8 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -692,6 +692,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
     PyGIMarshalFromPyFunc from_py_marshaller;
     int i;
     Py_ssize_t length;
+    gssize item_size;
     gboolean is_ptr_array;
     GArray *array_ = NULL;
     PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
@@ -720,13 +721,14 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
         return FALSE;
     }
 
+    item_size = sequence_cache->item_size;
     is_ptr_array = (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
     if (is_ptr_array) {
         array_ = (GArray *)g_ptr_array_new ();
     } else {
         array_ = g_array_sized_new (sequence_cache->is_zero_terminated,
                                     FALSE,
-                                    sequence_cache->item_size,
+                                    item_size,
                                     length);
     }
 
@@ -760,10 +762,37 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
          *        for ptr arrays than doing the evaluation
          *        and casting each loop iteration
          */
-        if (is_ptr_array)
+        if (is_ptr_array) {
             g_ptr_array_add((GPtrArray *)array_, item.v_pointer);
-        else
+        } else if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
+            PyGIInterfaceCache *item_iface_cache = (PyGIInterfaceCache *) sequence_cache->item_cache;
+            GIBaseInfo *base_info = (GIBaseInfo *) item_iface_cache->interface_info;
+            GIInfoType info_type = g_base_info_get_type (base_info);
+
+            switch (info_type) {
+                case GI_INFO_TYPE_UNION:
+                case GI_INFO_TYPE_STRUCT:
+                {
+                    PyGIArgCache *item_arg_cache = (PyGIArgCache *)item_iface_cache;
+                    PyGIMarshalCleanupFunc from_py_cleanup = item_arg_cache->from_py_cleanup;
+                    gboolean is_boxed = g_type_is_a (item_iface_cache->g_type, G_TYPE_BOXED);
+                    gboolean is_gvalue = item_iface_cache->g_type == G_TYPE_VALUE;
+
+                    if (!is_boxed || is_gvalue) {
+                        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 {
+                        g_array_insert_val (array_, i, item);
+                    }
+                    break;
+                }
+                default:
+                    g_array_insert_val (array_, i, item);
+            }
+        } else {
             g_array_insert_val (array_, i, item);
+        }
         continue;
 err:
         if (sequence_cache->item_cache->from_py_cleanup != NULL) {
diff --git a/tests/test_gi.py b/tests/test_gi.py
index c84ca23..dd91cb8 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -703,6 +703,35 @@ class TestArray(unittest.TestCase):
         object_ = GIMarshallingTests.Object()
         self.assertEquals([-1, 0, 1, 2], object_.method_array_return())
 
+    def test_array_enum_in(self):
+         GIMarshallingTests.array_enum_in([GIMarshallingTests.Enum.VALUE1,
+                                           GIMarshallingTests.Enum.VALUE2,
+                                           GIMarshallingTests.Enum.VALUE3])
+
+    def test_array_boxed_struct_in(self):
+         struct1 = GIMarshallingTests.BoxedStruct()
+         struct1.long_ = 1
+         struct2 = GIMarshallingTests.BoxedStruct()
+         struct2.long_ = 2
+         struct3 = GIMarshallingTests.BoxedStruct()
+         struct3.long_ = 3
+
+         GIMarshallingTests.array_struct_in([struct1, struct2, struct3])
+
+    def test_array_simple_struct_in(self):
+         struct1 = GIMarshallingTests.SimpleStruct()
+         struct1.long_ = 1
+         struct2 = GIMarshallingTests.SimpleStruct()
+         struct2.long_ = 2
+         struct3 = GIMarshallingTests.SimpleStruct()
+         struct3.long_ = 3
+
+         GIMarshallingTests.array_simple_struct_in([struct1, struct2, struct3])
+
+    def test_array_multi_array_key_value_in(self):
+         GIMarshallingTests.multi_array_key_value_in(["one", "two", "three"],
+                                                     [1, 2, 3])
+
     def test_array_fixed_out_struct(self):
         struct1, struct2 = GIMarshallingTests.array_fixed_out_struct()
 



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