[pybank] Add initial support for arrays as out arguments



commit 3e8b17d45811241258ebc8d34818c9a2bce54160
Author: Tomeu Vizoso <tomeu sugarlabs org>
Date:   Wed May 27 15:15:37 2009 +0200

    Add initial support for arrays as out arguments
---
 bank/bank-argument.c   |   56 +++++++++++++++++++++++++++++++++++++++++++++--
 bank/bank-info.c       |   29 ++++++++++++++++++++++++-
 bank/bank.h            |    1 +
 everything_unittest.py |    6 +++++
 4 files changed, 88 insertions(+), 4 deletions(-)

diff --git a/bank/bank-argument.c b/bank/bank-argument.c
index 0e64b79..ae2371b 100644
--- a/bank/bank-argument.c
+++ b/bank/bank-argument.c
@@ -169,6 +169,53 @@ glist_to_pyobject(GITypeTag list_tag, GITypeInfo *type_info, GList *list, GSList
 }
 
 PyObject *
+pyarray_to_pyobject(gpointer array, int length, GITypeInfo *type_info)
+{
+    PyObject *py_list;
+    PyObject *child_obj;
+    GITypeInfo *element_type = g_type_info_get_param_type (type_info, 0);
+    GITypeTag type_tag = g_type_info_get_tag(element_type);
+    gsize size;
+    char buf[256];
+    int i;
+
+    if (array == NULL)
+        return Py_None;
+
+    // FIXME: Doesn't seem right to have this here:
+    switch (type_tag) {
+    case GI_TYPE_TAG_INT:
+        size = sizeof(int);
+        break;
+    case GI_TYPE_TAG_INTERFACE:
+        size = sizeof(gpointer);
+        break;
+    default:
+        snprintf(buf, sizeof(buf), "Unimplemented type: %s\n", g_type_tag_to_string(type_tag));
+        PyErr_SetString(PyExc_TypeError, buf);
+        return NULL;
+    }
+
+    if ((py_list = PyList_New(0)) == NULL) {
+        return NULL;
+    }
+
+    for( i = 0; i < length; i++ ) {
+        gpointer current_element = array + i * size;
+
+        child_obj = pyg_argument_to_pyobject(current_element, element_type);
+        if (child_obj == NULL) {
+            Py_DECREF(py_list);
+            return NULL;
+        }
+        PyList_Append(py_list, child_obj);
+        Py_DECREF(child_obj);
+    }
+
+    return py_list;
+}
+
+PyObject *
 pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
 {
     GITypeTag type_tag;
@@ -312,8 +359,9 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
         }
         break;
     case GI_TYPE_TAG_ARRAY:
-	obj = Py_None;
-	break;
+        g_warning("pyg_argument_to_pyobject: use pyarray_to_pyobject instead for arrays");
+        obj = Py_None;
+        break;
     default:
 	g_print("<GArg->PyO> GITypeTag %s is unhandled\n",
 		g_type_tag_to_string(type_tag));
@@ -321,7 +369,9 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
 	break;
     }
 
-    Py_INCREF(obj);
+    if (obj != NULL)
+        Py_INCREF(obj);
+
     return obj;
 }
 
diff --git a/bank/bank-info.c b/bank/bank-info.c
index f60f616..0aaee0c 100644
--- a/bank/bank-info.c
+++ b/bank/bank-info.c
@@ -582,7 +582,34 @@ _wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
             g_assert(next_rval < n_return_values);
             g_assert(out_args_pos < expected_out_argc);
 
-            PyObject *obj = pyg_argument_to_pyobject(out_args[out_args_pos].v_pointer, arg_type_info);
+            PyObject *obj;
+            GITypeTag type_tag = g_type_info_get_tag(arg_type_info);
+
+            if (type_tag == GI_TYPE_TAG_ARRAY) {
+                GArgument *arg = out_args[out_args_pos].v_pointer;
+                gint length_arg_index = g_type_info_get_array_length(arg_type_info);
+                GArgument *length_arg;
+
+                if (is_method)
+                    length_arg_index--;
+
+                if (length_arg_index == -1) {
+                    PyErr_SetString(PyExc_NotImplementedError, "Need a field to specify the array length");
+                    return NULL;
+                }
+
+                length_arg = out_args[length_arg_index].v_pointer;
+
+                printf("index %d pointer %p\n", length_arg_index, length_arg);fflush(stdout);
+
+                if (length_arg == NULL) {
+                    PyErr_SetString(PyExc_RuntimeError, "Failed to get the length of the array");
+                    return NULL;
+                }
+
+                obj = pyarray_to_pyobject(arg->v_pointer, length_arg->v_int, arg_type_info);
+            } else
+                obj = pyg_argument_to_pyobject(out_args[out_args_pos].v_pointer, arg_type_info);
             if (obj == NULL) {
                 return NULL;
             }
diff --git a/bank/bank.h b/bank/bank.h
index b8f0181..d960483 100644
--- a/bank/bank.h
+++ b/bank/bank.h
@@ -76,4 +76,5 @@ GArgument pyg_argument_from_pyobject(PyObject *object,
 				     GITypeInfo *info);
 PyObject*  pyg_argument_to_pyobject(GArgument *arg,
 				    GITypeInfo *info);
+PyObject*  pyarray_to_pyobject(gpointer array, int length, GITypeInfo *info);
 
diff --git a/everything_unittest.py b/everything_unittest.py
index fd245f0..6dc67a6 100644
--- a/everything_unittest.py
+++ b/everything_unittest.py
@@ -277,5 +277,11 @@ class TestGIEverything(unittest.TestCase):
         s = TestSubclass()
         self.assertEquals(s.do_matrix('matrix'), 42)
 
+    def testArrayOut(self):
+        b, n_ints, ints = Everything.test_array_int_full_out2()
+        self.assertEquals(b, True)
+        self.assertEquals(n_ints, 5)
+        self.assertEquals(ints, [1, 2, 3, 4, 5])
+
 if __name__ == '__main__':
     unittest.main()



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