[pygi] One more step at refactoring _wrap_g_function_info_invoke
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygi] One more step at refactoring _wrap_g_function_info_invoke
- Date: Wed, 28 Apr 2010 17:14:00 +0000 (UTC)
commit 64fa8f936bad9a90628df446e690d67d947a0a22
Author: Tomeu Vizoso <tomeu sugarlabs org>
Date: Mon Apr 26 11:41:06 2010 +0200
One more step at refactoring _wrap_g_function_info_invoke
https://bugzilla.gnome.org/show_bug.cgi?id=616357
gi/pygi-callbacks.c | 22 +-
gi/pygi-callbacks.h | 4 +-
gi/pygi-info.c | 582 +++++++++++++++++++++++++++++----------------------
3 files changed, 346 insertions(+), 262 deletions(-)
---
diff --git a/gi/pygi-callbacks.c b/gi/pygi-callbacks.c
index fb852ff..7f5de9b 100644
--- a/gi/pygi-callbacks.c
+++ b/gi/pygi-callbacks.c
@@ -64,7 +64,7 @@ _pygi_destroy_notify_create(void)
gboolean
-_pygi_scan_for_callbacks (PyGIBaseInfo *function_info,
+_pygi_scan_for_callbacks (GIFunctionInfo *function_info,
gboolean is_method,
guint8 *callback_index,
guint8 *user_data_index,
@@ -76,7 +76,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo *function_info,
*user_data_index = G_MAXUINT8;
*destroy_notify_index = G_MAXUINT8;
- n_args = g_callable_info_get_n_args((GICallableInfo *)function_info->info);
+ n_args = g_callable_info_get_n_args((GICallableInfo *)function_info);
for (i = 0; i < n_args; i++) {
GIDirection direction;
GIArgInfo *arg_info;
@@ -84,7 +84,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo *function_info,
guint8 destroy, closure;
GITypeTag type_tag;
- arg_info = g_callable_info_get_arg((GICallableInfo*) function_info->info, i);
+ arg_info = g_callable_info_get_arg((GICallableInfo*) function_info, i);
type_info = g_arg_info_get_type(arg_info);
type_tag = g_type_info_get_tag(type_info);
@@ -99,8 +99,8 @@ _pygi_scan_for_callbacks (PyGIBaseInfo *function_info,
strcmp(g_base_info_get_name((GIBaseInfo*) interface_info), "DestroyNotify") == 0)) {
if (*callback_index != G_MAXUINT8) {
PyErr_Format(PyExc_TypeError, "Function %s.%s has multiple callbacks, not supported",
- g_base_info_get_namespace((GIBaseInfo*) function_info->info),
- g_base_info_get_name((GIBaseInfo*) function_info->info));
+ g_base_info_get_namespace((GIBaseInfo*) function_info),
+ g_base_info_get_name((GIBaseInfo*) function_info));
g_base_info_unref(interface_info);
return FALSE;
}
@@ -119,7 +119,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo *function_info,
if (destroy > 0 && destroy < n_args) {
if (*destroy_notify_index != G_MAXUINT8) {
PyErr_Format(PyExc_TypeError, "Function %s has multiple GDestroyNotify, not supported",
- g_base_info_get_name((GIBaseInfo*)function_info->info));
+ g_base_info_get_name((GIBaseInfo*)function_info));
return FALSE;
}
*destroy_notify_index = destroy;
@@ -128,7 +128,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo *function_info,
if (closure > 0 && closure < n_args) {
if (*user_data_index != G_MAXUINT8) {
PyErr_Format(PyExc_TypeError, "Function %s has multiple user_data arguments, not supported",
- g_base_info_get_name((GIBaseInfo*)function_info->info));
+ g_base_info_get_name((GIBaseInfo*)function_info));
return FALSE;
}
*user_data_index = closure;
@@ -142,7 +142,7 @@ _pygi_scan_for_callbacks (PyGIBaseInfo *function_info,
}
gboolean
-_pygi_create_callback (PyGIBaseInfo *function_info,
+_pygi_create_callback (GIBaseInfo *function_info,
gboolean is_method,
int n_args,
Py_ssize_t py_argc,
@@ -161,7 +161,7 @@ _pygi_create_callback (PyGIBaseInfo *function_info,
guint8 i, py_argv_pos;
PyObject *py_user_data;
- callback_arg = g_callable_info_get_arg((GICallableInfo*) function_info->info, callback_index);
+ callback_arg = g_callable_info_get_arg((GICallableInfo*) function_info, callback_index);
scope = g_arg_info_get_scope(callback_arg);
callback_type = g_arg_info_get_type(callback_arg);
@@ -194,8 +194,8 @@ _pygi_create_callback (PyGIBaseInfo *function_info,
if (!found_py_function
|| (py_function == Py_None || !PyCallable_Check(py_function))) {
PyErr_Format(PyExc_TypeError, "Error invoking %s.%s: Invalid callback given for argument %s",
- g_base_info_get_namespace((GIBaseInfo*) function_info->info),
- g_base_info_get_name((GIBaseInfo*) function_info->info),
+ g_base_info_get_namespace((GIBaseInfo*) function_info),
+ g_base_info_get_name((GIBaseInfo*) function_info),
g_base_info_get_name((GIBaseInfo*) callback_arg));
g_base_info_unref((GIBaseInfo*) callback_info);
g_base_info_unref((GIBaseInfo*) callback_type);
diff --git a/gi/pygi-callbacks.h b/gi/pygi-callbacks.h
index 7b3401d..4b98e3d 100644
--- a/gi/pygi-callbacks.h
+++ b/gi/pygi-callbacks.h
@@ -26,13 +26,13 @@ void _pygi_callback_notify_info_free(gpointer user_data);
PyGICClosure*_pygi_destroy_notify_create(void);
-gboolean _pygi_scan_for_callbacks (PyGIBaseInfo *self,
+gboolean _pygi_scan_for_callbacks (GIFunctionInfo *self,
gboolean is_method,
guint8 *callback_index,
guint8 *user_data_index,
guint8 *destroy_notify_index);
-gboolean _pygi_create_callback (PyGIBaseInfo *self,
+gboolean _pygi_create_callback (GIFunctionInfo *self,
gboolean is_method,
int n_args,
Py_ssize_t py_argc,
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 134a31d..44ab832 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -524,99 +524,105 @@ struct invocation_state
PyObject *return_value;
};
-
-static PyObject *
-_wrap_g_function_info_invoke (PyGIBaseInfo *self,
- PyObject *py_args)
+static void
+_initialize_invocation_state (struct invocation_state *state,
+ GIFunctionInfo *info,
+ PyObject *py_args)
{
- struct invocation_state s;
- gsize i;
-
- s.return_value = NULL;
- s.closure = NULL;
-
- {
- GIFunctionInfoFlags flags;
+ GIFunctionInfoFlags flags;
- flags = g_function_info_get_flags((GIFunctionInfo *)self->info);
- s.is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
- s.is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
- }
+ flags = g_function_info_get_flags(info);
+ state->is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
+ state->is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0;
/* Count arguments. */
- s.n_args = g_callable_info_get_n_args((GICallableInfo *)self->info);
- s.n_in_args = 0;
- s.n_out_args = 0;
- s.n_backup_args = 0;
- s.n_aux_in_args = 0;
- s.n_aux_out_args = 0;
+ state->n_args = g_callable_info_get_n_args((GICallableInfo *)info);
+ state->n_in_args = 0;
+ state->n_out_args = 0;
+ state->n_backup_args = 0;
+ state->n_aux_in_args = 0;
+ state->n_aux_out_args = 0;
/* Check the argument count. */
- s.n_py_args = PyTuple_Size(py_args);
- g_assert(s.n_py_args >= 0);
-
- s.error_arg_pos = -1;
-
- s.arg_infos = g_newa(GIArgInfo *, s.n_args);
- s.arg_type_infos = g_newa(GITypeInfo *, s.n_args);
+ state->n_py_args = PyTuple_Size(py_args);
+ g_assert(state->n_py_args >= 0);
+
+ state->error_arg_pos = -1;
+
+ state->arg_infos = g_slice_alloc0(sizeof(gpointer) * state->n_args);
+ state->arg_type_infos = g_slice_alloc0(sizeof(gpointer) * state->n_args);
+ state->args_is_auxiliary = g_slice_alloc0(sizeof(gboolean) * state->n_args);
+
+ state->return_value = NULL;
+ state->closure = NULL;
+ state->return_type_info = NULL;
+ state->args = NULL;
+ state->in_args = NULL;
+ state->out_args = NULL;
+ state->out_values = NULL;
+ state->backup_args = NULL;
+}
- s.args_is_auxiliary = g_newa(gboolean, s.n_args);
- memset(s.args_is_auxiliary, 0, sizeof(s.args_is_auxiliary) * s.n_args);
+static gboolean
+_prepare_invocation_state (struct invocation_state *state,
+ GIFunctionInfo *function_info, PyObject *py_args)
+{
+ gsize i;
- if (!_pygi_scan_for_callbacks (self, s.is_method,
- &s.callback_index, &s.user_data_index,
- &s.destroy_notify_index))
- return NULL;
+ if (!_pygi_scan_for_callbacks (function_info, state->is_method,
+ &state->callback_index, &state->user_data_index,
+ &state->destroy_notify_index))
+ return FALSE;
- if (s.callback_index != G_MAXUINT8) {
- if (!_pygi_create_callback (self, s.is_method,
- s.n_args, s.n_py_args,
- py_args, s.callback_index,
- s.user_data_index,
- s.destroy_notify_index, &s.closure))
- return NULL;
-
- s.args_is_auxiliary[s.callback_index] = FALSE;
- if (s.destroy_notify_index != G_MAXUINT8) {
- s.args_is_auxiliary[s.destroy_notify_index] = TRUE;
- s.n_aux_in_args += 1;
+ if (state->callback_index != G_MAXUINT8) {
+ if (!_pygi_create_callback (function_info, state->is_method,
+ state->n_args, state->n_py_args,
+ py_args, state->callback_index,
+ state->user_data_index,
+ state->destroy_notify_index, &state->closure))
+ return FALSE;
+
+ state->args_is_auxiliary[state->callback_index] = FALSE;
+ if (state->destroy_notify_index != G_MAXUINT8) {
+ state->args_is_auxiliary[state->destroy_notify_index] = TRUE;
+ state->n_aux_in_args += 1;
}
}
- if (s.is_method) {
+ if (state->is_method) {
/* The first argument is the instance. */
- s.n_in_args += 1;
+ state->n_in_args += 1;
}
/* We do a first (well, second) pass here over the function to scan for special cases.
* This is currently array+length combinations and GError.
*/
- for (i = 0; i < s.n_args; i++) {
+ for (i = 0; i < state->n_args; i++) {
GIDirection direction;
GITransfer transfer;
GITypeTag arg_type_tag;
- s.arg_infos[i] = g_callable_info_get_arg((GICallableInfo *)self->info,
+ state->arg_infos[i] = g_callable_info_get_arg((GICallableInfo *)function_info,
i);
- s.arg_type_infos[i] = g_arg_info_get_type(s.arg_infos[i]);
+ state->arg_type_infos[i] = g_arg_info_get_type(state->arg_infos[i]);
- direction = g_arg_info_get_direction(s.arg_infos[i]);
- transfer = g_arg_info_get_ownership_transfer(s.arg_infos[i]);
- arg_type_tag = g_type_info_get_tag(s.arg_type_infos[i]);
+ direction = g_arg_info_get_direction(state->arg_infos[i]);
+ transfer = g_arg_info_get_ownership_transfer(state->arg_infos[i]);
+ arg_type_tag = g_type_info_get_tag(state->arg_type_infos[i]);
if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
- s.n_in_args += 1;
+ state->n_in_args += 1;
if (transfer == GI_TRANSFER_CONTAINER) {
- s.n_backup_args += 1;
+ state->n_backup_args += 1;
}
}
if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
- s.n_out_args += 1;
+ state->n_out_args += 1;
}
if (direction == GI_DIRECTION_INOUT && transfer == GI_TRANSFER_NOTHING) {
- s.n_backup_args += 1;
+ state->n_backup_args += 1;
}
switch (arg_type_tag) {
@@ -624,159 +630,159 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
{
gint length_arg_pos;
- length_arg_pos = g_type_info_get_array_length(s.arg_type_infos[i]);
+ length_arg_pos = g_type_info_get_array_length(state->arg_type_infos[i]);
- if (s.is_method)
+ if (state->is_method)
length_arg_pos--; // length_arg_pos refers to C args
if (length_arg_pos < 0) {
break;
}
- g_assert(length_arg_pos < s.n_args);
- s.args_is_auxiliary[length_arg_pos] = TRUE;
+ g_assert(length_arg_pos < state->n_args);
+ state->args_is_auxiliary[length_arg_pos] = TRUE;
if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
- s.n_aux_in_args += 1;
+ state->n_aux_in_args += 1;
}
if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
- s.n_aux_out_args += 1;
+ state->n_aux_out_args += 1;
}
break;
}
case GI_TYPE_TAG_ERROR:
- g_warn_if_fail(s.error_arg_pos < 0);
- s.error_arg_pos = i;
+ g_warn_if_fail(state->error_arg_pos < 0);
+ state->error_arg_pos = i;
break;
default:
break;
}
}
- s.return_type_info = g_callable_info_get_return_type((GICallableInfo *)self->info);
- s.return_type_tag = g_type_info_get_tag(s.return_type_info);
+ state->return_type_info = g_callable_info_get_return_type((GICallableInfo *)function_info);
+ state->return_type_tag = g_type_info_get_tag(state->return_type_info);
- if (s.return_type_tag == GI_TYPE_TAG_ARRAY) {
+ if (state->return_type_tag == GI_TYPE_TAG_ARRAY) {
gint length_arg_pos;
- length_arg_pos = g_type_info_get_array_length(s.return_type_info);
+ length_arg_pos = g_type_info_get_array_length(state->return_type_info);
- if (s.is_method)
+ if (state->is_method)
length_arg_pos--; // length_arg_pos refers to C args
if (length_arg_pos >= 0) {
- g_assert(length_arg_pos < s.n_args);
- s.args_is_auxiliary[length_arg_pos] = TRUE;
- s.n_aux_out_args += 1;
+ g_assert(length_arg_pos < state->n_args);
+ state->args_is_auxiliary[length_arg_pos] = TRUE;
+ state->n_aux_out_args += 1;
}
}
- s.n_return_values = s.n_out_args - s.n_aux_out_args;
- if (s.return_type_tag != GI_TYPE_TAG_VOID) {
- s.n_return_values += 1;
+ state->n_return_values = state->n_out_args - state->n_aux_out_args;
+ if (state->return_type_tag != GI_TYPE_TAG_VOID) {
+ state->n_return_values += 1;
}
{
gsize n_py_args_expected;
Py_ssize_t py_args_pos;
- n_py_args_expected = s.n_in_args
- + (s.is_constructor ? 1 : 0)
- - s.n_aux_in_args
- - (s.error_arg_pos >= 0 ? 1 : 0);
+ n_py_args_expected = state->n_in_args
+ + (state->is_constructor ? 1 : 0)
+ - state->n_aux_in_args
+ - (state->error_arg_pos >= 0 ? 1 : 0);
- if (s.n_py_args != n_py_args_expected) {
+ if (state->n_py_args != n_py_args_expected) {
PyErr_Format(PyExc_TypeError,
"takes exactly %zd argument(s) (%zd given)",
- n_py_args_expected, s.n_py_args);
- goto out;
+ n_py_args_expected, state->n_py_args);
+ return FALSE;
}
- /* Check argument types. */
+ /* Check argument typestate-> */
py_args_pos = 0;
- if (s.is_constructor || s.is_method) {
+ if (state->is_constructor || state->is_method) {
py_args_pos += 1;
}
- for (i = 0; i < s.n_args; i++) {
+ for (i = 0; i < state->n_args; i++) {
GIDirection direction;
GITypeTag type_tag;
PyObject *py_arg;
gint retval;
gboolean allow_none;
- direction = g_arg_info_get_direction(s.arg_infos[i]);
- type_tag = g_type_info_get_tag(s.arg_type_infos[i]);
+ direction = g_arg_info_get_direction(state->arg_infos[i]);
+ type_tag = g_type_info_get_tag(state->arg_type_infos[i]);
if (direction == GI_DIRECTION_OUT
- || s.args_is_auxiliary[i]
+ || state->args_is_auxiliary[i]
|| type_tag == GI_TYPE_TAG_ERROR) {
continue;
}
- g_assert(py_args_pos < s.n_py_args);
+ g_assert(py_args_pos < state->n_py_args);
py_arg = PyTuple_GET_ITEM(py_args, py_args_pos);
- allow_none = g_arg_info_may_be_null(s.arg_infos[i]);
+ allow_none = g_arg_info_may_be_null(state->arg_infos[i]);
- retval = _pygi_g_type_info_check_object(s.arg_type_infos[i],
+ retval = _pygi_g_type_info_check_object(state->arg_type_infos[i],
py_arg,
allow_none);
if (retval < 0) {
- goto out;
+ return FALSE;
} else if (!retval) {
_PyGI_ERROR_PREFIX("argument %zd: ", py_args_pos);
- goto out;
+ return FALSE;
}
py_args_pos += 1;
}
- g_assert(py_args_pos == s.n_py_args);
+ g_assert(py_args_pos == state->n_py_args);
}
- s.args = g_newa(GArgument *, s.n_args);
- s.in_args = g_newa(GArgument, s.n_in_args);
- s.out_args = g_newa(GArgument, s.n_out_args);
- s.out_values = g_newa(GArgument, s.n_out_args);
- s.backup_args = g_newa(GArgument, s.n_backup_args);
+ state->args = g_slice_alloc0(sizeof(gpointer) * state->n_args);
+ state->in_args = g_slice_alloc0(sizeof(GArgument) * state->n_in_args);
+ state->out_args = g_slice_alloc0(sizeof(GArgument) * state->n_out_args);
+ state->out_values = g_slice_alloc0(sizeof(GArgument) * state->n_out_args);
+ state->backup_args = g_slice_alloc0(sizeof(GArgument) * state->n_backup_args);
/* Bind args so we can use an unique index. */
{
gsize in_args_pos;
gsize out_args_pos;
- in_args_pos = s.is_method ? 1 : 0;
+ in_args_pos = state->is_method ? 1 : 0;
out_args_pos = 0;
- for (i = 0; i < s.n_args; i++) {
+ for (i = 0; i < state->n_args; i++) {
GIDirection direction;
- direction = g_arg_info_get_direction(s.arg_infos[i]);
+ direction = g_arg_info_get_direction(state->arg_infos[i]);
switch (direction) {
case GI_DIRECTION_IN:
- g_assert(in_args_pos < s.n_in_args);
- s.args[i] = &s.in_args[in_args_pos];
+ g_assert(in_args_pos < state->n_in_args);
+ state->args[i] = &state->in_args[in_args_pos];
in_args_pos += 1;
break;
case GI_DIRECTION_INOUT:
- g_assert(in_args_pos < s.n_in_args);
- g_assert(out_args_pos < s.n_out_args);
- s.in_args[in_args_pos].v_pointer = &s.out_values[out_args_pos];
+ g_assert(in_args_pos < state->n_in_args);
+ g_assert(out_args_pos < state->n_out_args);
+ state->in_args[in_args_pos].v_pointer = &state->out_values[out_args_pos];
in_args_pos += 1;
case GI_DIRECTION_OUT:
- g_assert(out_args_pos < s.n_out_args);
- s.out_args[out_args_pos].v_pointer = &s.out_values[out_args_pos];
- s.out_values[out_args_pos].v_pointer = NULL;
- s.args[i] = &s.out_values[out_args_pos];
+ g_assert(out_args_pos < state->n_out_args);
+ state->out_args[out_args_pos].v_pointer = &state->out_values[out_args_pos];
+ state->out_values[out_args_pos].v_pointer = NULL;
+ state->args[i] = &state->out_values[out_args_pos];
out_args_pos += 1;
}
}
- g_assert(in_args_pos == s.n_in_args);
- g_assert(out_args_pos == s.n_out_args);
+ g_assert(in_args_pos == state->n_in_args);
+ g_assert(out_args_pos == state->n_out_args);
}
/* Convert the input arguments. */
@@ -787,19 +793,19 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
py_args_pos = 0;
backup_args_pos = 0;
- if (s.is_constructor) {
+ if (state->is_constructor) {
/* Skip the first argument. */
py_args_pos += 1;
- } else if (s.is_method) {
+ } else if (state->is_method) {
/* Get the instance. */
GIBaseInfo *container_info;
GIInfoType container_info_type;
PyObject *py_arg;
- container_info = g_base_info_get_container(self->info);
+ container_info = g_base_info_get_container(function_info);
container_info_type = g_base_info_get_type(container_info);
- g_assert(py_args_pos < s.n_py_args);
+ g_assert(py_args_pos < state->n_py_args);
py_arg = PyTuple_GET_ITEM(py_args, py_args_pos);
switch(container_info_type) {
@@ -811,22 +817,22 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)container_info);
if (g_type_is_a(type, G_TYPE_BOXED)) {
- g_assert(s.n_in_args > 0);
- s.in_args[0].v_pointer = pyg_boxed_get(py_arg, void);
+ g_assert(state->n_in_args > 0);
+ state->in_args[0].v_pointer = pyg_boxed_get(py_arg, void);
} else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
- g_assert(s.n_in_args > 0);
- s.in_args[0].v_pointer = pyg_pointer_get(py_arg, void);
+ g_assert(state->n_in_args > 0);
+ state->in_args[0].v_pointer = pyg_pointer_get(py_arg, void);
} else {
PyErr_Format(PyExc_TypeError, "unable to convert an instance of '%s'", g_type_name(type));
- goto out;
+ return FALSE;
}
break;
}
case GI_INFO_TYPE_OBJECT:
case GI_INFO_TYPE_INTERFACE:
- g_assert(s.n_in_args > 0);
- s.in_args[0].v_pointer = pygobject_get(py_arg);
+ g_assert(state->n_in_args > 0);
+ state->in_args[0].v_pointer = pygobject_get(py_arg);
break;
default:
/* Other types don't have methods. */
@@ -836,34 +842,34 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
py_args_pos += 1;
}
- for (i = 0; i < s.n_args; i++) {
+ for (i = 0; i < state->n_args; i++) {
GIDirection direction;
- if (i == s.callback_index) {
- s.args[i]->v_pointer = s.closure->closure;
+ if (i == state->callback_index) {
+ state->args[i]->v_pointer = state->closure->closure;
py_args_pos++;
continue;
- } else if (i == s.user_data_index) {
- s.args[i]->v_pointer = s.closure;
+ } else if (i == state->user_data_index) {
+ state->args[i]->v_pointer = state->closure;
py_args_pos++;
continue;
- } else if (i == s.destroy_notify_index) {
- s.args[i]->v_pointer = _pygi_destroy_notify_create();
+ } else if (i == state->destroy_notify_index) {
+ state->args[i]->v_pointer = _pygi_destroy_notify_create();
continue;
}
- if (s.args_is_auxiliary[i]) {
+ if (state->args_is_auxiliary[i]) {
continue;
}
- direction = g_arg_info_get_direction(s.arg_infos[i]);
+ direction = g_arg_info_get_direction(state->arg_infos[i]);
if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
PyObject *py_arg;
GITypeTag arg_type_tag;
GITransfer transfer;
- arg_type_tag = g_type_info_get_tag(s.arg_type_infos[i]);
+ arg_type_tag = g_type_info_get_tag(state->arg_type_infos[i]);
if (arg_type_tag == GI_TYPE_TAG_ERROR) {
GError **error;
@@ -871,26 +877,26 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
error = g_slice_new(GError *);
*error = NULL;
- s.args[i]->v_pointer = error;
+ state->args[i]->v_pointer = error;
continue;
}
- transfer = g_arg_info_get_ownership_transfer(s.arg_infos[i]);
+ transfer = g_arg_info_get_ownership_transfer(state->arg_infos[i]);
- g_assert(py_args_pos < s.n_py_args);
+ g_assert(py_args_pos < state->n_py_args);
py_arg = PyTuple_GET_ITEM(py_args, py_args_pos);
- *s.args[i] = _pygi_argument_from_object(py_arg, s.arg_type_infos[i], transfer);
+ *state->args[i] = _pygi_argument_from_object(py_arg, state->arg_type_infos[i], transfer);
if (PyErr_Occurred()) {
/* TODO: release previous input arguments. */
- goto out;
+ return FALSE;
}
if (direction == GI_DIRECTION_INOUT && transfer == GI_TRANSFER_NOTHING) {
/* We need to keep a copy of the argument to be able to release it later. */
- g_assert(backup_args_pos < s.n_backup_args);
- s.backup_args[backup_args_pos] = *s.args[i];
+ g_assert(backup_args_pos < state->n_backup_args);
+ state->backup_args[backup_args_pos] = *state->args[i];
backup_args_pos += 1;
} else if (transfer == GI_TRANSFER_CONTAINER) {
/* We need to keep a copy of the items to be able to release them later. */
@@ -901,25 +907,25 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
gsize item_size;
GArray *new_array;
- array = s.args[i]->v_pointer;
+ array = state->args[i]->v_pointer;
item_size = g_array_get_element_size(array);
new_array = g_array_sized_new(FALSE, FALSE, item_size, array->len);
g_array_append_vals(new_array, array->data, array->len);
- g_assert(backup_args_pos < s.n_backup_args);
- s.backup_args[backup_args_pos].v_pointer = new_array;
+ g_assert(backup_args_pos < state->n_backup_args);
+ state->backup_args[backup_args_pos].v_pointer = new_array;
break;
}
case GI_TYPE_TAG_GLIST:
- g_assert(backup_args_pos < s.n_backup_args);
- s.backup_args[backup_args_pos].v_pointer = g_list_copy(s.args[i]->v_pointer);
+ g_assert(backup_args_pos < state->n_backup_args);
+ state->backup_args[backup_args_pos].v_pointer = g_list_copy(state->args[i]->v_pointer);
break;
case GI_TYPE_TAG_GSLIST:
- g_assert(backup_args_pos < s.n_backup_args);
- s.backup_args[backup_args_pos].v_pointer = g_slist_copy(s.args[i]->v_pointer);
+ g_assert(backup_args_pos < state->n_backup_args);
+ state->backup_args[backup_args_pos].v_pointer = g_slist_copy(state->args[i]->v_pointer);
break;
case GI_TYPE_TAG_GHASH:
{
@@ -927,13 +933,13 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
GList *keys;
GList *values;
- hash_table = s.args[i]->v_pointer;
+ hash_table = state->args[i]->v_pointer;
keys = g_hash_table_get_keys(hash_table);
values = g_hash_table_get_values(hash_table);
- g_assert(backup_args_pos < s.n_backup_args);
- s.backup_args[backup_args_pos].v_pointer = g_list_concat(keys, values);
+ g_assert(backup_args_pos < state->n_backup_args);
+ state->backup_args[backup_args_pos].v_pointer = g_list_concat(keys, values);
break;
}
@@ -948,19 +954,19 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
GArray *array;
gssize length_arg_pos;
- array = s.args[i]->v_pointer;
+ array = state->args[i]->v_pointer;
- length_arg_pos = g_type_info_get_array_length(s.arg_type_infos[i]);
- if (s.is_method)
+ length_arg_pos = g_type_info_get_array_length(state->arg_type_infos[i]);
+ if (state->is_method)
length_arg_pos--; // length_arg_pos refers to C args
if (length_arg_pos >= 0) {
/* Set the auxiliary argument holding the length. */
- s.args[length_arg_pos]->v_size = array->len;
+ state->args[length_arg_pos]->v_size = array->len;
}
/* Get rid of the GArray. */
if (array != NULL) {
- s.args[i]->v_pointer = array->data;
+ state->args[i]->v_pointer = array->data;
if (direction != GI_DIRECTION_INOUT || transfer != GI_TRANSFER_NOTHING) {
/* The array hasn't been referenced anywhere, so free it to avoid losing memory. */
@@ -973,35 +979,39 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
}
}
- g_assert(py_args_pos == s.n_py_args);
- g_assert(backup_args_pos == s.n_backup_args);
+ g_assert(py_args_pos == state->n_py_args);
+ g_assert(backup_args_pos == state->n_backup_args);
}
- /* Invoke the callable. */
- {
- GError *error;
- gint retval;
+ return TRUE;
+}
- error = NULL;
+static gboolean
+_invoke_function (struct invocation_state *state,
+ GIFunctionInfo *function_info, PyObject *py_args)
+{
+ GError *error;
+ gint retval;
- retval = g_function_info_invoke((GIFunctionInfo *)self->info,
- s.in_args, s.n_in_args, s.out_args, s.n_out_args, &s.return_arg, &error);
- if (!retval) {
- g_assert(error != NULL);
- /* TODO: raise the right error, out of the error domain. */
- PyErr_SetString(PyExc_RuntimeError, error->message);
- g_error_free(error);
+ error = NULL;
- /* TODO: release input arguments. */
+ retval = g_function_info_invoke((GIFunctionInfo *)function_info,
+ state->in_args, state->n_in_args, state->out_args, state->n_out_args, &state->return_arg, &error);
+ if (!retval) {
+ g_assert(error != NULL);
+ /* TODO: raise the right error, out of the error domain. */
+ PyErr_SetString(PyExc_RuntimeError, error->message);
+ g_error_free(error);
- goto out;
- }
+ /* TODO: release input arguments. */
+
+ return FALSE;
}
- if (s.error_arg_pos >= 0) {
+ if (state->error_arg_pos >= 0) {
GError **error;
- error = s.args[s.error_arg_pos]->v_pointer;
+ error = state->args[state->error_arg_pos]->v_pointer;
if (*error != NULL) {
/* TODO: raise the right error, out of the error domain, if applicable. */
@@ -1010,33 +1020,42 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
/* TODO: release input arguments. */
- goto out;
+ return FALSE;
}
}
+ return TRUE;
+}
+
+static gboolean
+_process_invocation_state (struct invocation_state *state,
+ GIFunctionInfo *function_info, PyObject *py_args)
+{
+ gsize i;
+
/* Convert the return value. */
- if (s.is_constructor) {
+ if (state->is_constructor) {
PyTypeObject *py_type;
GIBaseInfo *info;
GIInfoType info_type;
GITransfer transfer;
- g_assert(s.n_py_args > 0);
+ g_assert(state->n_py_args > 0);
py_type = (PyTypeObject *)PyTuple_GET_ITEM(py_args, 0);
- info = g_type_info_get_interface(s.return_type_info);
+ info = g_type_info_get_interface(state->return_type_info);
g_assert(info != NULL);
info_type = g_base_info_get_type(info);
- transfer = g_callable_info_get_caller_owns((GICallableInfo *)self->info);
+ transfer = g_callable_info_get_caller_owns((GICallableInfo *)function_info);
switch (info_type) {
case GI_INFO_TYPE_UNION:
/* TODO */
PyErr_SetString(PyExc_NotImplementedError, "creating unions is not supported yet");
g_base_info_unref(info);
- goto out;
+ return FALSE;
case GI_INFO_TYPE_STRUCT:
{
GType type;
@@ -1044,36 +1063,36 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info);
if (g_type_is_a(type, G_TYPE_BOXED)) {
- if (s.return_arg.v_pointer == NULL) {
+ if (state->return_arg.v_pointer == NULL) {
PyErr_SetString(PyExc_TypeError, "constructor returned NULL");
break;
}
g_warn_if_fail(transfer == GI_TRANSFER_EVERYTHING);
- s.return_value = _pygi_boxed_new(py_type, s.return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
+ state->return_value = _pygi_boxed_new(py_type, state->return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
} else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
- if (s.return_arg.v_pointer == NULL) {
+ if (state->return_arg.v_pointer == NULL) {
PyErr_SetString(PyExc_TypeError, "constructor returned NULL");
break;
}
g_warn_if_fail(transfer == GI_TRANSFER_NOTHING);
- s.return_value = _pygi_struct_new(py_type, s.return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
+ state->return_value = _pygi_struct_new(py_type, state->return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
} else {
PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", py_type->tp_name);
g_base_info_unref(info);
- goto out;
+ return FALSE;
}
break;
}
case GI_INFO_TYPE_OBJECT:
- if (s.return_arg.v_pointer == NULL) {
+ if (state->return_arg.v_pointer == NULL) {
PyErr_SetString(PyExc_TypeError, "constructor returned NULL");
break;
}
- s.return_value = pygobject_new(s.return_arg.v_pointer);
+ state->return_value = pygobject_new(state->return_arg.v_pointer);
if (transfer == GI_TRANSFER_EVERYTHING) {
/* The new wrapper increased the reference count, so decrease it. */
- g_object_unref (s.return_arg.v_pointer);
+ g_object_unref (state->return_arg.v_pointer);
}
break;
default:
@@ -1083,32 +1102,32 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
g_base_info_unref(info);
- if (s.return_value == NULL) {
+ if (state->return_value == NULL) {
/* TODO: release arguments. */
- goto out;
+ return FALSE;
}
} else {
GITransfer transfer;
- if (s.return_type_tag == GI_TYPE_TAG_ARRAY) {
+ if (state->return_type_tag == GI_TYPE_TAG_ARRAY) {
/* Create a #GArray. */
- s.return_arg.v_pointer = _pygi_argument_to_array(&s.return_arg, s.args, s.return_type_info, s.is_method);
+ state->return_arg.v_pointer = _pygi_argument_to_array(&state->return_arg, state->args, state->return_type_info, state->is_method);
}
- transfer = g_callable_info_get_caller_owns((GICallableInfo *)self->info);
+ transfer = g_callable_info_get_caller_owns((GICallableInfo *)function_info);
- s.return_value = _pygi_argument_to_object(&s.return_arg, s.return_type_info, transfer);
- if (s.return_value == NULL) {
+ state->return_value = _pygi_argument_to_object(&state->return_arg, state->return_type_info, transfer);
+ if (state->return_value == NULL) {
/* TODO: release argument. */
- goto out;
+ return FALSE;
}
- _pygi_argument_release(&s.return_arg, s.return_type_info, transfer, GI_DIRECTION_OUT);
+ _pygi_argument_release(&state->return_arg, state->return_type_info, transfer, GI_DIRECTION_OUT);
- if (s.return_type_tag == GI_TYPE_TAG_ARRAY
+ if (state->return_type_tag == GI_TYPE_TAG_ARRAY
&& transfer == GI_TRANSFER_NOTHING) {
/* We created a #GArray, so free it. */
- s.return_arg.v_pointer = g_array_free(s.return_arg.v_pointer, FALSE);
+ state->return_arg.v_pointer = g_array_free(state->return_arg.v_pointer, FALSE);
}
}
@@ -1120,68 +1139,68 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
backup_args_pos = 0;
return_values_pos = 0;
- if (s.n_return_values > 1) {
+ if (state->n_return_values > 1) {
/* Return a tuple. */
PyObject *return_values;
- return_values = PyTuple_New(s.n_return_values);
+ return_values = PyTuple_New(state->n_return_values);
if (return_values == NULL) {
/* TODO: release arguments. */
- goto out;
+ return FALSE;
}
- if (s.return_type_tag == GI_TYPE_TAG_VOID) {
+ if (state->return_type_tag == GI_TYPE_TAG_VOID) {
/* The current return value is None. */
- Py_DECREF(s.return_value);
+ Py_DECREF(state->return_value);
} else {
/* Put the return value first. */
- g_assert(s.return_value != NULL);
- PyTuple_SET_ITEM(return_values, return_values_pos, s.return_value);
+ g_assert(state->return_value != NULL);
+ PyTuple_SET_ITEM(return_values, return_values_pos, state->return_value);
return_values_pos += 1;
}
- s.return_value = return_values;
+ state->return_value = return_values;
}
- for (i = 0; i < s.n_args; i++) {
+ for (i = 0; i < state->n_args; i++) {
GIDirection direction;
GITypeTag type_tag;
GITransfer transfer;
- if (s.args_is_auxiliary[i]) {
+ if (state->args_is_auxiliary[i]) {
/* Auxiliary arguments are handled at the same time as their relatives. */
continue;
}
- direction = g_arg_info_get_direction(s.arg_infos[i]);
- transfer = g_arg_info_get_ownership_transfer(s.arg_infos[i]);
+ direction = g_arg_info_get_direction(state->arg_infos[i]);
+ transfer = g_arg_info_get_ownership_transfer(state->arg_infos[i]);
- type_tag = g_type_info_get_tag(s.arg_type_infos[i]);
+ type_tag = g_type_info_get_tag(state->arg_type_infos[i]);
if (type_tag == GI_TYPE_TAG_ARRAY
&& (direction != GI_DIRECTION_IN || transfer == GI_TRANSFER_NOTHING)) {
/* Create a #GArray. */
- s.args[i]->v_pointer = _pygi_argument_to_array(s.args[i], s.args, s.arg_type_infos[i], s.is_method);
+ state->args[i]->v_pointer = _pygi_argument_to_array(state->args[i], state->args, state->arg_type_infos[i], state->is_method);
}
if (direction == GI_DIRECTION_INOUT || direction == GI_DIRECTION_OUT) {
/* Convert the argument. */
PyObject *obj;
- obj = _pygi_argument_to_object(s.args[i], s.arg_type_infos[i], transfer);
+ obj = _pygi_argument_to_object(state->args[i], state->arg_type_infos[i], transfer);
if (obj == NULL) {
/* TODO: release arguments. */
- goto out;
+ return FALSE;
}
- g_assert(return_values_pos < s.n_return_values);
+ g_assert(return_values_pos < state->n_return_values);
- if (s.n_return_values > 1) {
- PyTuple_SET_ITEM(s.return_value, return_values_pos, obj);
+ if (state->n_return_values > 1) {
+ PyTuple_SET_ITEM(state->return_value, return_values_pos, obj);
} else {
/* The current return value is None. */
- Py_DECREF(s.return_value);
- s.return_value = obj;
+ Py_DECREF(state->return_value);
+ state->return_value = obj;
}
return_values_pos += 1;
@@ -1196,8 +1215,8 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
case GI_TYPE_TAG_ARRAY:
case GI_TYPE_TAG_GLIST:
case GI_TYPE_TAG_GSLIST:
- g_assert(backup_args_pos < s.n_backup_args);
- _pygi_argument_release(&s.backup_args[backup_args_pos], s.arg_type_infos[i],
+ g_assert(backup_args_pos < state->n_backup_args);
+ _pygi_argument_release(&state->backup_args[backup_args_pos], state->arg_type_infos[i],
transfer, GI_DIRECTION_IN);
break;
case GI_TYPE_TAG_GHASH:
@@ -1208,11 +1227,11 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
gsize length;
gsize j;
- key_type_info = g_type_info_get_param_type(s.arg_type_infos[i], 0);
- value_type_info = g_type_info_get_param_type(s.arg_type_infos[i], 1);
+ key_type_info = g_type_info_get_param_type(state->arg_type_infos[i], 0);
+ value_type_info = g_type_info_get_param_type(state->arg_type_infos[i], 1);
- g_assert(backup_args_pos < s.n_backup_args);
- item = s.backup_args[backup_args_pos].v_pointer;
+ g_assert(backup_args_pos < state->n_backup_args);
+ item = state->backup_args[backup_args_pos].v_pointer;
length = g_list_length(item) / 2;
@@ -1226,7 +1245,7 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
}
- g_list_free(s.backup_args[backup_args_pos].v_pointer);
+ g_list_free(state->backup_args[backup_args_pos].v_pointer);
break;
}
@@ -1236,54 +1255,119 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self,
if (direction == GI_DIRECTION_INOUT) {
/* Release the output argument. */
- _pygi_argument_release(s.args[i], s.arg_type_infos[i], GI_TRANSFER_CONTAINER,
+ _pygi_argument_release(state->args[i], state->arg_type_infos[i], GI_TRANSFER_CONTAINER,
GI_DIRECTION_OUT);
}
backup_args_pos += 1;
} else if (direction == GI_DIRECTION_INOUT) {
if (transfer == GI_TRANSFER_NOTHING) {
- g_assert(backup_args_pos < s.n_backup_args);
- _pygi_argument_release(&s.backup_args[backup_args_pos], s.arg_type_infos[i],
+ g_assert(backup_args_pos < state->n_backup_args);
+ _pygi_argument_release(&state->backup_args[backup_args_pos], state->arg_type_infos[i],
GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
backup_args_pos += 1;
}
- _pygi_argument_release(s.args[i], s.arg_type_infos[i], transfer,
+ _pygi_argument_release(state->args[i], state->arg_type_infos[i], transfer,
GI_DIRECTION_OUT);
} else {
- _pygi_argument_release(s.args[i], s.arg_type_infos[i], transfer, direction);
+ _pygi_argument_release(state->args[i], state->arg_type_infos[i], transfer, direction);
}
if (type_tag == GI_TYPE_TAG_ARRAY
&& (direction != GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)) {
/* We created a #GArray and it has not been released above, so free it. */
- s.args[i]->v_pointer = g_array_free(s.args[i]->v_pointer, FALSE);
+ state->args[i]->v_pointer = g_array_free(state->args[i]->v_pointer, FALSE);
}
}
- g_assert(s.n_return_values <= 1 || return_values_pos == s.n_return_values);
- g_assert(backup_args_pos == s.n_backup_args);
+ g_assert(state->n_return_values <= 1 || return_values_pos == state->n_return_values);
+ g_assert(backup_args_pos == state->n_backup_args);
}
-out:
- g_base_info_unref((GIBaseInfo *)s.return_type_info);
+ return TRUE;
+}
+
+static void
+_free_invocation_state (struct invocation_state *state)
+{
+ gsize i;
+
+ if (state->return_type_info != NULL) {
+ g_base_info_unref((GIBaseInfo *)state->return_type_info);
+ }
+
+ if (state->closure != NULL) {
+ if (state->closure->scope == GI_SCOPE_TYPE_CALL)
+ _pygi_invoke_closure_free(state->closure);
+ }
+
+ for (i = 0; i < state->n_args; i++) {
+ g_base_info_unref((GIBaseInfo *)state->arg_type_infos[i]);
+ g_base_info_unref((GIBaseInfo *)state->arg_infos[i]);
+ }
+
+ if (state->arg_infos != NULL) {
+ g_slice_free1(sizeof(gpointer) * state->n_args, state->arg_infos);
+ }
+
+ if (state->arg_type_infos != NULL) {
+ g_slice_free1(sizeof(gpointer) * state->n_args, state->arg_type_infos);
+ }
+
+ if (state->args != NULL) {
+ g_slice_free1(sizeof(gpointer) * state->n_args, state->args);
+ }
+
+ if (state->args_is_auxiliary != NULL) {
+ g_slice_free1(sizeof(gboolean) * state->n_args, state->args_is_auxiliary);
+ }
- if (s.closure != NULL) {
- if (s.closure->scope == GI_SCOPE_TYPE_CALL)
- _pygi_invoke_closure_free(s.closure);
+ if (state->in_args != NULL) {
+ g_slice_free1(sizeof(GArgument) * state->n_in_args, state->in_args);
}
- for (i = 0; i < s.n_args; i++) {
- g_base_info_unref((GIBaseInfo *)s.arg_type_infos[i]);
- g_base_info_unref((GIBaseInfo *)s.arg_infos[i]);
+ if (state->out_args != NULL) {
+ g_slice_free1(sizeof(GArgument) * state->n_out_args, state->out_args);
+ }
+
+ if (state->out_values != NULL) {
+ g_slice_free1(sizeof(GArgument) * state->n_out_args, state->out_values);
+ }
+
+ if (state->backup_args != NULL) {
+ g_slice_free1(sizeof(GArgument) * state->n_backup_args, state->backup_args);
}
if (PyErr_Occurred()) {
- Py_CLEAR(s.return_value);
+ Py_CLEAR(state->return_value);
+ }
+}
+
+
+static PyObject *
+_wrap_g_function_info_invoke (PyGIBaseInfo *self, PyObject *py_args)
+{
+ struct invocation_state state;
+
+ _initialize_invocation_state (&state, self->info, py_args);
+
+ if (!_prepare_invocation_state (&state, self->info, py_args)) {
+ _free_invocation_state (&state);
+ return NULL;
+ }
+
+ if (!_invoke_function (&state, self->info, py_args)) {
+ _free_invocation_state (&state);
+ return NULL;
+ }
+
+ if (!_process_invocation_state (&state, self->info, py_args)) {
+ _free_invocation_state (&state);
+ return NULL;
}
- return s.return_value;
+ return state.return_value;
}
static PyMethodDef _PyGIFunctionInfo_methods[] = {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]