From 3e8b17d45811241258ebc8d34818c9a2bce54160 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Wed, 27 May 2009 13:15:37 +0000 Subject: Add initial support for arrays as out arguments --- 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("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() -- cgit v0.9.1