[pygobject] Use array lengths specified on struct fields



commit 4e130d72a5492fc00c61a816eddccdbc4f558b91
Author: Simon Feltman <sfeltman src gnome org>
Date:   Sun Aug 17 19:03:32 2014 -0700

    Use array lengths specified on struct fields
    
    Add array length marshalling policy for struct fields. This fixes accessing
    C array fields on structs which also specify a length field.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=688792

 gi/pygi-argument.c |   14 ++++++------
 gi/pygi-argument.h |    4 +++
 gi/pygi-info.c     |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 68 insertions(+), 9 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 03c0a9c..3d643fe 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -35,10 +35,10 @@
 #include "pygi-struct-marshal.h"
 #include "pygi-error.h"
 
-static gboolean
-gi_argument_to_gssize (GIArgument *arg_in,
-                       GITypeTag  type_tag,
-                       gssize *gssize_out)
+gboolean
+pygi_argument_to_gssize (GIArgument *arg_in,
+                         GITypeTag  type_tag,
+                         gssize *gssize_out)
 {
     switch (type_tag) {
       case GI_TYPE_TAG_INT8:
@@ -786,9 +786,9 @@ _pygi_argument_array_length_marshal (gsize length_arg_index,
 
     length_arg = _pygi_argument_from_g_value (&(values[length_arg_index]),
                                               &length_type_info);
-    if (!gi_argument_to_gssize (&length_arg,
-                                g_type_info_get_tag (&length_type_info),
-                                &array_len)) {
+    if (!pygi_argument_to_gssize (&length_arg,
+                                  g_type_info_get_tag (&length_type_info),
+                                  &array_len)) {
         return -1;
     }
 
diff --git a/gi/pygi-argument.h b/gi/pygi-argument.h
index c8f2f1e..73770bd 100644
--- a/gi/pygi-argument.h
+++ b/gi/pygi-argument.h
@@ -76,6 +76,10 @@ void _pygi_argument_release (GIArgument   *arg,
 
 void _pygi_argument_init (void);
 
+gboolean pygi_argument_to_gssize (GIArgument *arg_in,
+                                  GITypeTag  type_tag,
+                                  gssize *gssize_out);
+
 G_END_DECLS
 
 #endif /* __PYGI_ARGUMENT_H__ */
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index c07d113..4df3359 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -1761,6 +1761,57 @@ static PyMethodDef _PyGIValueInfo_methods[] = {
 /* GIFieldInfo */
 PYGLIB_DEFINE_TYPE ("gi.FieldInfo", PyGIFieldInfo_Type, PyGIBaseInfo);
 
+static gssize
+_struct_field_array_length_marshal (gsize length_index,
+                                    void *container_ptr,
+                                    void *struct_data_ptr)
+{
+    gssize array_len = -1;
+    GIFieldInfo *array_len_field = NULL;
+    GIArgument arg = {0};
+    GIBaseInfo *container_info = (GIBaseInfo *)container_ptr;
+
+    switch (g_base_info_get_type (container_info)) {
+        case GI_INFO_TYPE_UNION:
+            array_len_field = g_union_info_get_field ((GIUnionInfo *)container_info, length_index);
+            break;
+        case GI_INFO_TYPE_STRUCT:
+            array_len_field = g_struct_info_get_field ((GIStructInfo *)container_info, length_index);
+            break;
+        case GI_INFO_TYPE_OBJECT:
+            array_len_field = g_object_info_get_field ((GIObjectInfo *)container_info, length_index);
+            break;
+        default:
+            /* Other types don't have fields. */
+            g_assert_not_reached();
+    }
+
+    if (array_len_field == NULL) {
+        return -1;
+    }
+
+    if (g_field_info_get_field (array_len_field, struct_data_ptr, &arg)) {
+        GITypeInfo *array_len_type_info;
+
+        array_len_type_info = g_field_info_get_type (array_len_field);
+        if (array_len_type_info == NULL) {
+            goto out;
+        }
+
+        if (!pygi_argument_to_gssize (&arg,
+                                      g_type_info_get_tag (array_len_type_info),
+                                      &array_len)) {
+            array_len = -1;
+        }
+
+        g_base_info_unref (array_len_type_info);
+    }
+
+out:
+    g_base_info_unref (array_len_field);
+    return array_len;
+}
+
 static PyObject *
 _wrap_g_field_info_get_value (PyGIBaseInfo *self,
                               PyObject     *args)
@@ -1850,8 +1901,12 @@ _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, NULL,
-                                                   field_type_info, &free_array);
+        value.v_pointer = _pygi_argument_to_array (&value,
+                                                   _struct_field_array_length_marshal,
+                                                   container_info,
+                                                   pointer,
+                                                   field_type_info,
+                                                   &free_array);
     }
 
 argument_to_object:


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