[pygobject/gsoc2009: 13/160] Refactore _wrap_g_function_info_invoke
- From: Simon van der Linden <svdlinden src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [pygobject/gsoc2009: 13/160] Refactore _wrap_g_function_info_invoke
- Date: Fri, 14 Aug 2009 21:23:10 +0000 (UTC)
commit e0c3ccca456f3d7133c7855956b6801b5572aa08
Author: Simon van der Linden <simon vanderlinden student uclouvain be>
Date: Tue Jun 23 00:35:00 2009 +0200
Refactore _wrap_g_function_info_invoke
Refactore _wrap_g_function_info_invoke to make it more modular.
girepository/bank-info.c | 533 +++++++++++++++++++++++++---------------------
1 files changed, 292 insertions(+), 241 deletions(-)
---
diff --git a/girepository/bank-info.c b/girepository/bank-info.c
index 9adafed..50df71d 100644
--- a/girepository/bank-info.c
+++ b/girepository/bank-info.c
@@ -328,329 +328,380 @@ _wrap_g_function_info_is_method(PyGIBaseInfo *self)
static PyObject *
_wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
{
- GArgument *in_args;
- GArgument *out_args;
- GArgument *out_values;
- GArgument return_arg;
- int n_args;
- int expected_in_argc;
- int expected_out_argc;
- int i;
- int argv_pos;
- int in_args_pos;
- int out_args_pos;
- GError *error;
- gboolean failed;
- GIFunctionInfoFlags flags;
gboolean is_method;
gboolean is_constructor;
- gboolean invoke_ok;
+
+ guint n_args;
+ guint n_in_args;
+ guint n_out_args;
+ Py_ssize_t n_py_args;
+ guint n_return_values;
+
+ GICallableInfo *callable_info;
GITypeInfo *return_info;
GITypeTag return_tag;
- PyObject **return_values;
- int n_return_values;
- int next_rval;
- PyObject *retval;
- PyObject *py_arg;
- flags = g_function_info_get_flags((GIFunctionInfo*)self->info);
- is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
- is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
+ GArgument *in_args;
+ GArgument *out_args;
+ GArgument *out_values;
+ GArgument return_arg;
+ PyObject *return_value;
+
+ guint i;
- expected_in_argc = 0;
- expected_out_argc = 0;
+ callable_info = (GICallableInfo *)self->info;
+
+ {
+ GIFunctionInfoFlags flags;
+
+ flags = g_function_info_get_flags((GIFunctionInfo *)callable_info);
+ is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
+ is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
+ }
+
+ /* Count arguments. */
+ n_args = g_callable_info_get_n_args(callable_info);
+ n_py_args = PyTuple_Size(args);
+ n_in_args = is_method ? 1 : 0; /* The first argument is the instance. */
+ n_out_args = 0;
- n_args = g_callable_info_get_n_args( (GICallableInfo*) self->info);
for (i = 0; i < n_args; i++) {
GIDirection direction;
GIArgInfo *arg_info;
- arg_info = g_callable_info_get_arg( (GICallableInfo*) self->info, i);
+ arg_info = g_callable_info_get_arg(callable_info, i);
direction = g_arg_info_get_direction(arg_info);
- if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
- expected_in_argc += 1;
- if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
- expected_out_argc += 1;
- g_base_info_unref( (GIBaseInfo*) arg_info);
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
+ n_in_args += 1;
+ }
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
+ n_out_args += 1;
+ }
+
+ g_base_info_unref((GIBaseInfo *)arg_info);
}
- /*
- g_debug("Call is to %s %s.%s with expected: %d in args, %d out args, %d total args",
- is_method ? "method" : "function",
- g_base_info_get_namespace( (GIBaseInfo*) self->info),
- g_base_info_get_name( (GIBaseInfo*) self->info),
- expected_in_argc,
- expected_out_argc,
- n_args);
- */
- if (is_method)
- expected_in_argc += 1;
- in_args = g_newa(GArgument, expected_in_argc);
- out_args = g_newa(GArgument, expected_out_argc);
+ /* Get the arguments. */
+ in_args = g_newa(GArgument, n_in_args);
+ out_args = g_newa(GArgument, n_out_args);
/* each out arg is a pointer, they point to these values */
/* FIXME: This will break for caller-allocates funcs:
http://bugzilla.gnome.org/show_bug.cgi?id=573314 */
- out_values = g_newa(GArgument, expected_out_argc);
-
- failed = FALSE;
- in_args_pos = 0; /* index into in_args */
- out_args_pos = 0; /* into out_args */
- argv_pos = 0; /* index into argv */
+ out_values = g_newa(GArgument, n_out_args);
+
+ {
+ guint in_args_pos = 0;
+ guint out_args_pos = 0;
+ Py_ssize_t py_args_pos = 0;
+
+ if (is_method && !is_constructor) {
+ /* Get the instance. */
+ GIBaseInfo *container;
+ GIInfoType container_info_type;
+ PyObject *py_arg;
+
+ container = g_base_info_get_container((GIBaseInfo *)callable_info);
+ container_info_type = g_base_info_get_type(container);
+
+ py_arg = PyTuple_GetItem(args, py_args_pos);
+ g_assert(py_arg != NULL);
+
+ if (py_arg == Py_None) {
+ in_args[in_args_pos].v_pointer = NULL;
+ } else if (container_info_type == GI_INFO_TYPE_STRUCT || container_info_type == GI_INFO_TYPE_BOXED) {
+ PyObject *py_buffer;
+ PyBufferProcs *py_buffer_procs;
+ py_buffer = PyObject_GetAttrString((PyObject *)py_arg, "__buffer__");
+ if (py_buffer == NULL) {
+ g_base_info_unref(container);
+ return NULL;
+ }
+ py_buffer_procs = py_buffer->ob_type->tp_as_buffer;
+ (*py_buffer_procs->bf_getreadbuffer)(py_buffer, 0, &in_args[in_args_pos].v_pointer);
+ } else { /* by fallback is always object */
+ in_args[in_args_pos].v_pointer = pygobject_get(py_arg);
+ }
- if (is_method && !is_constructor) {
- GIBaseInfo *container = g_base_info_get_container((GIBaseInfo *) self->info);
- GIInfoType type = g_base_info_get_type(container);
+ g_base_info_unref(container);
- py_arg = PyTuple_GetItem(args, 0);
- if (!py_arg) {
- PyErr_SetString(PyExc_ValueError, "Calling a method without passing an instance");
- return NULL;
+ in_args_pos += 1;
+ py_args_pos += 1;
+ } else if (is_constructor) {
+ /* Skip the first argument. */
+ py_args_pos += 1;
}
- if (py_arg == Py_None) {
- in_args[0].v_pointer = NULL;
- } else if (type == GI_INFO_TYPE_STRUCT || type == GI_INFO_TYPE_BOXED) {
- PyObject *pybuffer = PyObject_GetAttrString((PyObject *)py_arg,
- "__buffer__");
- PyBufferProcs *buffer_procs = pybuffer->ob_type->tp_as_buffer;
- (*buffer_procs->bf_getreadbuffer)(pybuffer, 0, &in_args[0].v_pointer);
- } else { /* by fallback is always object */
- in_args[0].v_pointer = pygobject_get(py_arg);
- }
- ++in_args_pos;
- }
- for (i = 0; i < n_args; i++) {
- GIDirection direction;
- GIArgInfo *arg_info;
- GArgument *out_value;
+ for (i = 0; i < n_args; i++) {
+ GIDirection direction;
+ GIArgInfo *arg_info;
+ GArgument *out_value = NULL;
- arg_info = g_callable_info_get_arg( (GICallableInfo*) self->info, i);
- direction = g_arg_info_get_direction(arg_info);
+ arg_info = g_callable_info_get_arg(callable_info, i);
+ direction = g_arg_info_get_direction(arg_info);
- out_value = NULL;
- if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
- g_assert(out_args_pos < expected_out_argc);
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
+ g_assert(out_args_pos < n_out_args);
- out_value = &out_values[out_args_pos];
- out_args[out_args_pos].v_pointer = out_value;
- ++out_args_pos;
- }
+ out_value = &out_values[out_args_pos];
+ out_args[out_args_pos].v_pointer = out_value;
+ out_args_pos += 1;
+ }
- if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
- if (is_method || is_constructor)
- py_arg = PyTuple_GetItem(args, i + 1);
- else
- py_arg = PyTuple_GetItem(args, i);
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
+ PyObject *py_arg;
- GArgument in_value = pyg_argument_from_pyobject(py_arg, g_arg_info_get_type(arg_info));
+ g_assert(py_args_pos < n_py_args);
+ py_arg = PyTuple_GetItem(args, py_args_pos);
+ g_assert(py_arg != NULL);
- ++argv_pos;
+ GArgument in_value = pyg_argument_from_pyobject(py_arg, g_arg_info_get_type(arg_info));
- if (direction == GI_DIRECTION_IN) {
- in_args[in_args_pos] = in_value;
- } else {
- /* INOUT means we pass a pointer */
- g_assert(out_value != NULL);
- *out_value = in_value;
- in_args[in_args_pos].v_pointer = out_value;
+ g_assert(in_args_pos < n_in_args);
+ if (direction == GI_DIRECTION_IN) {
+ /* Pass the value. */
+ in_args[in_args_pos] = in_value;
+ } else {
+ /* Pass a pointer to the value. */
+ g_assert(out_value != NULL);
+ *out_value = in_value;
+ in_args[in_args_pos].v_pointer = out_value;
+ }
+
+ in_args_pos += 1;
+ py_args_pos += 1;
}
- ++in_args_pos;
+ g_base_info_unref((GIBaseInfo *)arg_info);
}
- g_base_info_unref( (GIBaseInfo*) arg_info);
-
- if (failed)
- break;
+ g_assert(in_args_pos == n_in_args);
+ g_assert(out_args_pos == n_out_args);
+ g_assert(py_args_pos == n_py_args);
}
- if (failed) {
- PyErr_SetString(PyExc_ValueError, "Failed to convert all args.");
- return NULL;
+ /* Invoke the callable. */
+ {
+ GError *error = NULL;
+
+ if (!g_function_info_invoke((GIFunctionInfo *)callable_info,
+ in_args, n_in_args,
+ out_args, n_out_args,
+ &return_arg,
+ &error)) {
+ g_assert(error != NULL);
+ PyErr_Format(PyExc_RuntimeError, "Error invoking %s.%s(): %s",
+ g_base_info_get_namespace((GIBaseInfo *)callable_info),
+ g_base_info_get_name((GIBaseInfo *)callable_info),
+ error->message);
+ g_error_free(error);
+ return NULL;
+ }
}
- g_assert(in_args_pos == expected_in_argc);
- g_assert(out_args_pos == expected_out_argc);
+ /* Get return value. */
+ return_info = g_callable_info_get_return_type(callable_info);
+ return_tag = g_type_info_get_tag(return_info);
- error = NULL;
- invoke_ok = g_function_info_invoke( (GIFunctionInfo*) self->info,
- in_args, expected_in_argc,
- out_args, expected_out_argc,
- &return_arg,
- &error);
+ n_return_values = n_out_args;
+ if (return_tag != GI_TYPE_TAG_VOID) {
+ n_return_values += 1;
- return_info = g_callable_info_get_return_type( (GICallableInfo*) self->info);
- g_assert(return_info != NULL);
+ if (!is_constructor) {
+ /* Convert the return value. */
+ return_value = pyg_argument_to_pyobject(&return_arg, return_info);
+ g_assert(return_value != NULL);
+ } else {
+ /* Wrap the return value inside the first argument. */
- if (!invoke_ok) {
- char buf[256];
- snprintf(buf, sizeof(buf), "Error invoking %s.%s: %s",
- g_base_info_get_namespace( (GIBaseInfo*) self->info),
- g_base_info_get_name( (GIBaseInfo*) self->info),
- error->message);
+ g_assert(n_py_args > 0);
+ return_value = PyTuple_GetItem(args, 0);
+ g_assert(return_value != NULL);
- g_assert(error != NULL);
- PyErr_SetString(PyExc_RuntimeError, buf);
- g_error_free(error);
+ Py_INCREF(return_value);
- return NULL;
- }
+ if (return_tag == GI_TYPE_TAG_INTERFACE) {
+ GIBaseInfo *interface_info;
+ GIInfoType interface_info_type;
- return_tag = g_type_info_get_tag(return_info);
+ interface_info = g_type_info_get_interface(return_info);
+ interface_info_type = g_base_info_get_type(interface_info);
- if (is_constructor) {
- py_arg = PyTuple_GetItem(args, 0);
+ if (interface_info_type == GI_INFO_TYPE_STRUCT || interface_info_type == GI_INFO_TYPE_BOXED) {
+ /* FIXME: We should reuse this. Perhaps by separating the
+ * wrapper creation from the binding to the wrapper.
+ */
+ gsize size;
+ PyObject *buffer;
+ int retval;
- if (return_tag == GI_TYPE_TAG_INTERFACE) {
- GIBaseInfo *interface_info = g_type_info_get_interface(return_info);
- GIInfoType interface_type = g_base_info_get_type(interface_info);
+ size = g_struct_info_get_size ((GIStructInfo *)return_info);
+ g_assert(size > 0);
- if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
- // FIXME: We should reuse this. Perhaps by separating the
- // wrapper creation from the binding to the wrapper.
- gsize size = g_struct_info_get_size ((GIStructInfo*)return_info);
- PyObject *buffer = PyBuffer_FromReadWriteMemory(return_arg.v_pointer, size);
+ buffer = PyBuffer_FromReadWriteMemory(return_arg.v_pointer, size);
- //PyObject *dict = PyObject_GetDict(py_arg);
- PyObject_SetAttrString(py_arg, "__buffer__", buffer);
+ retval = PyObject_SetAttrString(return_value, "__buffer__", buffer);
+ g_assert(retval != -1);
+ } else {
+ PyGObject *gobject;
- Py_INCREF(py_arg);
- return py_arg;
- } else {
- PyGObject *self = (PyGObject *) py_arg;
- if (self->obj != NULL) {
- PyErr_SetString(PyExc_ValueError, "Calling constructor on an instance that isn't a GObject");
- return NULL;
+ gobject = (PyGObject *) return_value;
+ gobject->obj = return_arg.v_pointer;
+
+ g_object_ref(gobject->obj);
+ pygobject_register_wrapper(return_value);
}
- self->obj = return_arg.v_pointer;
- g_object_ref(return_arg.v_pointer);
- pygobject_register_wrapper(py_arg);
- Py_INCREF(py_arg);
- return py_arg;
+
+ g_base_info_unref(interface_info);
+ } else {
+ /* TODO */
+ g_base_info_unref((GIBaseInfo *)return_info);
+ PyErr_SetString(PyExc_NotImplementedError, "constructor return_tag != GI_TYPE_TAG_INTERFACE");
+ return NULL;
}
- } else {
- PyErr_SetString(PyExc_NotImplementedError, "");
- return NULL;
}
+ } else {
+ return_value = NULL;
}
- retval = NULL;
+ /* Get output arguments and release input arguments. */
+ {
+ guint in_args_pos;
+ guint out_args_pos;
+ guint return_values_pos;
- next_rval = 0; /* index into return_values */
+ return_values_pos = 0;
- n_return_values = expected_out_argc;
- if (return_tag != GI_TYPE_TAG_VOID)
- n_return_values += 1;
+ if (n_return_values > 1) {
+ /* Return a tuple. */
+ PyObject *return_values;
- return_values = g_newa(PyObject*, n_return_values);
- if (!is_constructor && n_return_values > 0) {
- if (return_tag != GI_TYPE_TAG_VOID) {
- PyObject *obj = pyg_argument_to_pyobject(&return_arg, return_info);
- if (obj == NULL) {
+ return_values = PyTuple_New(n_return_values);
+ if (return_values == NULL) {
+ g_base_info_unref((GIBaseInfo *)return_info);
return NULL;
}
- return_values[next_rval] = obj;
- ++next_rval;
- }
- }
-
- /* We walk over all args, release in args (if allocated) and convert
- * all out args
- */
- in_args_pos = is_method ? 1 : 0; /* index into in_args */
- out_args_pos = 0; /* into out_args */
+ if (return_tag != GI_TYPE_TAG_VOID) {
+ /* Put the return value first. */
+ int retval;
+ g_assert(return_value != NULL);
+ retval = PyTuple_SetItem(return_values, return_values_pos, return_value);
+ g_assert(retval == 0);
+ return_values_pos += 1;
+ }
- for (i = 0; i < n_args; i++) {
- GIDirection direction;
- GIArgInfo *arg_info;
- GITypeInfo *arg_type_info;
+ return_value = return_values;
+ }
- arg_info = g_callable_info_get_arg( (GICallableInfo*) self->info, i);
- direction = g_arg_info_get_direction(arg_info);
+ in_args_pos = is_method ? 1 : 0;
+ out_args_pos = 0;
- arg_type_info = g_arg_info_get_type(arg_info);
+ for (i = 0; i < n_args; i++) {
+ GIDirection direction;
+ GIArgInfo *arg_info;
+ GITypeInfo *arg_type_info;
- if (direction == GI_DIRECTION_IN) {
- g_assert(in_args_pos < expected_in_argc);
+ arg_info = g_callable_info_get_arg(callable_info, i);
+ arg_type_info = g_arg_info_get_type(arg_info);
- ++in_args_pos;
- } else {
- /* INOUT or OUT */
- if (direction == GI_DIRECTION_INOUT)
- g_assert(in_args_pos < expected_in_argc);
- g_assert(next_rval < n_return_values);
- g_assert(out_args_pos < expected_out_argc);
+ direction = g_arg_info_get_direction(arg_info);
- PyObject *obj;
- GITypeTag type_tag = g_type_info_get_tag(arg_type_info);
+ if (direction == GI_DIRECTION_IN) {
+ g_assert(in_args_pos < n_in_args);
- 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;
+ /* TODO: Release if allocated. */
- if (is_method)
- length_arg_index--;
+ in_args_pos += 1;
+ } else {
+ PyObject *obj;
+ GITypeTag type_tag;
+ int retval;
- if (length_arg_index == -1) {
- PyErr_SetString(PyExc_NotImplementedError, "Need a field to specify the array length");
- return NULL;
+ if (direction == GI_DIRECTION_INOUT) {
+ g_assert(in_args_pos < n_in_args);
+ }
+ g_assert(out_args_pos < n_out_args);
+
+ type_tag = g_type_info_get_tag(arg_type_info);
+
+ if (type_tag == GI_TYPE_TAG_ARRAY) {
+ /* FIXME: Verify all that... */
+
+ gint length_arg_index;
+ GArgument *length_arg;
+ GArgument *arg;
+
+ length_arg_index = g_type_info_get_array_length(arg_type_info);
+
+ if (is_method) {
+ /* XXX: Why? */
+ length_arg_index -= 1;
+ }
+
+ if (length_arg_index == -1) {
+ g_base_info_unref((GIBaseInfo *)arg_type_info);
+ g_base_info_unref((GIBaseInfo *)arg_info);
+ g_base_info_unref((GIBaseInfo *)return_info);
+ PyErr_SetString(PyExc_NotImplementedError, "Need a field to specify the array length");
+ return NULL;
+ }
+
+ length_arg = out_args[length_arg_index].v_pointer;
+
+ if (length_arg == NULL) {
+ g_base_info_unref((GIBaseInfo *)arg_type_info);
+ g_base_info_unref((GIBaseInfo *)arg_info);
+ g_base_info_unref((GIBaseInfo *)return_info);
+ PyErr_SetString(PyExc_RuntimeError, "Failed to get the length of the array");
+ return NULL;
+ }
+
+ arg = (GArgument *)out_args[out_args_pos].v_pointer;
+ 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);
}
- length_arg = out_args[length_arg_index].v_pointer;
+ g_assert(obj != NULL);
+ g_assert(return_values_pos < n_return_values);
- if (length_arg == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "Failed to get the length of the array");
- return NULL;
+ if (n_return_values > 1) {
+ g_assert(return_value != NULL);
+
+ retval = PyTuple_SetItem(return_value, return_values_pos, obj);
+ g_assert(retval == 0);
+ } else {
+ g_assert(return_value == NULL);
+ return_value = obj;
}
- 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;
+ if (direction == GI_DIRECTION_INOUT) {
+ in_args_pos += 1;
+ }
+ out_args_pos += 1;
+ return_values_pos += 1;
}
- return_values[next_rval] = obj;
- if (direction == GI_DIRECTION_INOUT)
- ++in_args_pos;
-
- ++out_args_pos;
-
- ++next_rval;
+ g_base_info_unref((GIBaseInfo *)arg_type_info);
+ g_base_info_unref((GIBaseInfo *)arg_info);
}
- g_base_info_unref( (GIBaseInfo*) arg_type_info);
- g_base_info_unref( (GIBaseInfo*) arg_info);
- }
-
- g_assert(next_rval == n_return_values);
- g_assert(out_args_pos == expected_out_argc);
- g_assert(in_args_pos == expected_in_argc);
-
- if (n_return_values > 0) {
- if (n_return_values == 0) {
- retval = Py_None;
- Py_INCREF(retval);
- } else if (n_return_values == 1) {
- retval = return_values[0];
- } else {
- retval = PyTuple_New(n_return_values);
- for (i = 0; i < n_return_values; i++) {
- PyTuple_SetItem(retval, i, return_values[i]);
- }
+ if (n_return_values > 1) {
+ g_assert(return_values_pos == n_return_values);
}
+ g_assert(out_args_pos == n_out_args);
+ g_assert(in_args_pos == n_in_args);
}
- g_base_info_unref( (GIBaseInfo*) return_info);
+ g_base_info_unref((GIBaseInfo *)return_info);
- if (retval == NULL) {
+ if (return_value == NULL) {
Py_INCREF(Py_None);
- retval = Py_None;
+ return_value = Py_None;
}
- return retval;
+ return return_value;
}
static PyMethodDef _PyGIFunctionInfo_methods[] = {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]