[pygobject/invoke-rewrite] [gi] make new invoke-ng codepath compile correctly
- From: John Palmieri <johnp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject/invoke-rewrite] [gi] make new invoke-ng codepath compile correctly
- Date: Tue, 22 Mar 2011 20:14:23 +0000 (UTC)
commit 86c436978c933f6ebe17627abe98325ce66f6baa
Author: John (J5) Palmieri <johnp redhat com>
Date: Tue Mar 22 16:13:58 2011 -0400
[gi] make new invoke-ng codepath compile correctly
configure.ac | 4 +
gi/Makefile.am | 5 +-
gi/pygi-cache.c | 2 +-
gi/pygi-invoke-ng.c | 841 ----------------------
gi/pygi-marshal.c | 1962 +--------------------------------------------------
gi/pygi-private.h | 4 +-
6 files changed, 9 insertions(+), 2809 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 8eedd15..c39d19a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -127,6 +127,10 @@ dnl Build with the new caching invoker
AC_ARG_ENABLE(invoke-ng,
AC_HELP_STRING([--enable-invoke-ng], [Enable the new caching invoke path]),,
enable_invoke_ng=no)
+if test "${enable_invoke_ng}" != no; then
+ AC_DEFINE(ENABLE_INVOKE_NG, 1, Enable the new invoke caching code path)
+fi
+
AM_CONDITIONAL(ENABLE_INVOKE_NG, test x$enable_invoke_ng != xno)
dnl Building documentation
diff --git a/gi/Makefile.am b/gi/Makefile.am
index 82ca98a..8bd5057 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -31,6 +31,7 @@ _gi_la_SOURCES = \
pygi-repository.h \
pygi-info.c \
pygi-info.h \
+ pygi-invoke.h \
pygi-foreign.c \
pygi-foreign.h \
pygi-foreign-gvariant.c \
@@ -59,7 +60,6 @@ _gi_la_SOURCES = \
if ENABLE_INVOKE_NG
_gi_la_SOURCES += \
pygi-invoke-ng.c \
- pygi-invoke-ng.h \
pygi-invoke-state-struct.h \
pygi-cache.h \
pygi-cache.c \
@@ -67,8 +67,7 @@ _gi_la_SOURCES += \
pygi-marshal.h
else
_gi_la_SOURCES += \
- pygi-invoke.c \
- pygi-invoke.h
+ pygi-invoke.c
endif
_gi_cairo_la_CFLAGS = \
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 230017f..6cf4108 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -21,7 +21,7 @@
#include "pygi-info.h"
#include "pygi-cache.h"
-#include "pygi-argument.h"
+#include "pygi-marshal.h"
#include "pygi-type.h"
#include <girepository.h>
diff --git a/gi/pygi-invoke-ng.c b/gi/pygi-invoke-ng.c
index f88965a..0275976 100644
--- a/gi/pygi-invoke-ng.c
+++ b/gi/pygi-invoke-ng.c
@@ -23,532 +23,6 @@
#include "pygi-invoke.h"
-struct invocation_state
-{
- gboolean is_method;
- gboolean is_constructor;
-
- gsize n_args;
- gsize n_in_args;
- gsize n_out_args;
- gsize n_backup_args;
- Py_ssize_t n_py_args;
- gsize n_aux_in_args;
- gsize n_aux_out_args;
- gsize n_return_values;
-
- guint8 callback_index;
- guint8 user_data_index;
- guint8 destroy_notify_index;
- PyGICClosure *closure;
-
- glong error_arg_pos;
-
- GIArgInfo **arg_infos;
- GITypeInfo **arg_type_infos;
- GITypeInfo *return_type_info;
- GITypeTag return_type_tag;
-
- GIArgument **args;
- gboolean *args_is_auxiliary;
-
- GIArgument *in_args;
- GIArgument *out_args;
- GIArgument *out_values;
- GIArgument *backup_args;
- GIArgument return_arg;
-
- PyObject *return_value;
-};
-
-static void
-_initialize_invocation_state (struct invocation_state *state,
- GIFunctionInfo *info,
- PyObject *py_args)
-{
- GIFunctionInfoFlags flags;
-
- 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. */
- 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. */
- 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;
-}
-
-static gboolean
-_prepare_invocation_state (struct invocation_state *state,
- GIFunctionInfo *function_info, PyObject *py_args)
-{
- gsize i;
-
- if (!_pygi_scan_for_callbacks (function_info,
- state->is_method,
- &state->callback_index, &state->user_data_index,
- &state->destroy_notify_index))
- return FALSE;
-
- if (state->callback_index != G_MAXUINT8) {
-
- if (!_pygi_create_callback (function_info,
- state->is_method,
- state->is_constructor,
- 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 (state->is_method) {
- /* The first argument is the instance. */
- 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, GError and GValue.
- */
- for (i = 0; i < state->n_args; i++) {
- GIDirection direction;
- GITransfer transfer;
- GITypeTag arg_type_tag;
-
- state->arg_infos[i] = g_callable_info_get_arg ( (GICallableInfo *) function_info,
- i);
-
- state->arg_type_infos[i] = g_arg_info_get_type (state->arg_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) {
- state->n_in_args += 1;
- }
- if (direction == GI_DIRECTION_INOUT) {
- state->n_backup_args += 1;
- }
- if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
- state->n_out_args += 1;
- }
-
- switch (arg_type_tag) {
- case GI_TYPE_TAG_ARRAY:
- {
- gint length_arg_pos;
-
- length_arg_pos = g_type_info_get_array_length (state->arg_type_infos[i]);
-
- if (length_arg_pos < 0) {
- break;
- }
-
- /* For array lengths, we're going to delete the length argument;
- * so remove the extra backup we just added above */
- if (direction == GI_DIRECTION_INOUT) {
- state->n_backup_args -= 1;
- }
-
- 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) {
- state->n_aux_in_args += 1;
- }
- if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
- state->n_aux_out_args += 1;
- }
-
- break;
- }
- case GI_TYPE_TAG_ERROR:
- g_warn_if_fail (state->error_arg_pos < 0);
- state->error_arg_pos = i;
- break;
- default:
- break;
- }
- }
-
- 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 (state->return_type_tag == GI_TYPE_TAG_ARRAY) {
- gint length_arg_pos;
- length_arg_pos = g_type_info_get_array_length (state->return_type_info);
-
- if (length_arg_pos >= 0) {
- g_assert (length_arg_pos < state->n_args);
- state->args_is_auxiliary[length_arg_pos] = TRUE;
- state->n_aux_out_args += 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 = state->n_in_args
- + (state->is_constructor ? 1 : 0)
- - state->n_aux_in_args
- - (state->error_arg_pos >= 0 ? 1 : 0);
-
- if (state->n_py_args != n_py_args_expected) {
- PyErr_Format (PyExc_TypeError,
- "%s() takes exactly %zd argument(s) (%zd given)",
- g_base_info_get_name ( (GIBaseInfo *) function_info),
- n_py_args_expected, state->n_py_args);
- return FALSE;
- }
-
- /* Check argument typestate-> */
- py_args_pos = 0;
- if (state->is_constructor || state->is_method) {
- py_args_pos += 1;
- }
-
- 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 (state->arg_infos[i]);
- type_tag = g_type_info_get_tag (state->arg_type_infos[i]);
-
- if (direction == GI_DIRECTION_OUT
- || state->args_is_auxiliary[i]
- || type_tag == GI_TYPE_TAG_ERROR) {
- continue;
- }
-
- 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 (state->arg_infos[i]);
-
- retval = _pygi_g_type_info_check_object (state->arg_type_infos[i],
- py_arg,
- allow_none);
-
- if (retval < 0) {
- return FALSE;
- } else if (!retval) {
- _PyGI_ERROR_PREFIX ("argument %zd: ", py_args_pos);
- return FALSE;
- }
-
- py_args_pos += 1;
- }
-
- g_assert (py_args_pos == state->n_py_args);
- }
-
- state->args = g_slice_alloc0 (sizeof (gpointer) * state->n_args);
- state->in_args = g_slice_alloc0 (sizeof (GIArgument) * state->n_in_args);
- state->out_args = g_slice_alloc0 (sizeof (GIArgument) * state->n_out_args);
- state->out_values = g_slice_alloc0 (sizeof (GIArgument) * state->n_out_args);
- state->backup_args = g_slice_alloc0 (sizeof (GIArgument) * state->n_backup_args);
-
- /* Bind args so we can use an unique index. */
- {
- gsize in_args_pos;
- gsize out_args_pos;
-
- in_args_pos = state->is_method ? 1 : 0;
- out_args_pos = 0;
-
- for (i = 0; i < state->n_args; i++) {
- GIDirection direction;
- GIBaseInfo *info;
- gboolean is_caller_allocates;
-
- direction = g_arg_info_get_direction (state->arg_infos[i]);
- is_caller_allocates = g_arg_info_is_caller_allocates (state->arg_infos[i]);
-
- switch (direction) {
- case GI_DIRECTION_IN:
- 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 < 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 < state->n_out_args);
-
- /* caller allocates only applies to structures but GI has
- * no way to denote that yet, so we only use caller allocates
- * if we see a structure
- */
- if (is_caller_allocates) {
- GITypeTag type_tag;
-
- is_caller_allocates = FALSE;
- type_tag = g_type_info_get_tag (state->arg_type_infos[i]);
-
- if (type_tag == GI_TYPE_TAG_INTERFACE) {
- GIInfoType info_type;
-
- info = g_type_info_get_interface (state->arg_type_infos[i]);
- g_assert (info != NULL);
- info_type = g_base_info_get_type (info);
-
- if (info_type == GI_INFO_TYPE_STRUCT)
- is_caller_allocates = TRUE;
- }
- }
-
- if (is_caller_allocates) {
- /* if caller allocates only use one level of indirection */
- state->out_args[out_args_pos].v_pointer = NULL;
- state->args[i] = &state->out_args[out_args_pos];
- if (g_type_is_a (g_registered_type_info_get_g_type (info), G_TYPE_BOXED)) {
- state->args[i]->v_pointer = _pygi_boxed_alloc (info, NULL);
- } else if (g_struct_info_is_foreign((GIStructInfo *) info) ) {
- PyObject *foreign_struct =
- pygi_struct_foreign_convert_from_g_argument(state->arg_type_infos[i], NULL);
-
- pygi_struct_foreign_convert_to_g_argument(
- foreign_struct,
- state->arg_type_infos[i],
- GI_TRANSFER_EVERYTHING,
- state->args[i]);
-
- Py_DECREF(foreign_struct);
- } else {
- gssize size = g_struct_info_get_size ( (GIStructInfo *) info);
- state->args[i]->v_pointer = g_malloc0 (size);
- }
- } else {
- 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 == state->n_in_args);
- g_assert (out_args_pos == state->n_out_args);
- }
-
- /* Convert the input arguments. */
- {
- Py_ssize_t py_args_pos;
- gsize backup_args_pos;
-
- py_args_pos = 0;
- backup_args_pos = 0;
-
- if (state->is_constructor) {
- /* Skip the first argument. */
- py_args_pos += 1;
- } else if (state->is_method) {
- /* Get the instance. */
- GIBaseInfo *container_info;
- GIInfoType container_info_type;
- PyObject *py_arg;
- gint check_val;
-
- container_info = g_base_info_get_container (function_info);
- container_info_type = g_base_info_get_type (container_info);
-
- g_assert (py_args_pos < state->n_py_args);
- py_arg = PyTuple_GET_ITEM (py_args, py_args_pos);
-
- /* In python 2 python takes care of checking the type
- * of the self instance. In python 3 it does not
- * so we have to check it here
- */
- check_val = _pygi_g_type_interface_check_object(container_info,
- py_arg);
- if (check_val < 0) {
- return FALSE;
- } else if (!check_val) {
- _PyGI_ERROR_PREFIX ("instance: ");
- return FALSE;
- }
-
- switch (container_info_type) {
- case GI_INFO_TYPE_UNION:
- case GI_INFO_TYPE_STRUCT:
- {
- GType type;
-
- type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) container_info);
-
- if (g_type_is_a (type, G_TYPE_BOXED)) {
- 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 (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));
- return FALSE;
- }
-
- break;
- }
- case GI_INFO_TYPE_OBJECT:
- case GI_INFO_TYPE_INTERFACE:
- 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. */
- g_assert_not_reached();
- }
-
- py_args_pos += 1;
- }
-
- for (i = 0; i < state->n_args; i++) {
- GIDirection direction;
-
- if (i == state->callback_index) {
- if (state->closure)
- state->args[i]->v_pointer = state->closure->closure;
- else
- /* Some callbacks params accept NULL */
- state->args[i]->v_pointer = NULL;
- py_args_pos++;
- continue;
- } else if (i == state->user_data_index) {
- state->args[i]->v_pointer = state->closure;
- py_args_pos++;
- continue;
- } else if (i == state->destroy_notify_index) {
- if (state->closure) {
- /* No need to clean up if the callback is NULL */
- PyGICClosure *destroy_notify = _pygi_destroy_notify_create();
- state->args[i]->v_pointer = destroy_notify->closure;
- }
- continue;
- }
-
- if (state->args_is_auxiliary[i]) {
- continue;
- }
-
- 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 (state->arg_type_infos[i]);
-
- if (arg_type_tag == GI_TYPE_TAG_ERROR) {
- GError **error;
-
- error = g_slice_new (GError *);
- *error = NULL;
-
- state->args[i]->v_pointer = error;
- continue;
- }
-
- transfer = g_arg_info_get_ownership_transfer (state->arg_infos[i]);
-
- g_assert (py_args_pos < state->n_py_args);
- py_arg = PyTuple_GET_ITEM (py_args, py_args_pos);
-
- *state->args[i] = _pygi_argument_from_object (py_arg, state->arg_type_infos[i], transfer);
-
- if (PyErr_Occurred()) {
- /* TODO: release previous input arguments. */
- return FALSE;
- }
-
- if (direction == GI_DIRECTION_INOUT) {
- /* We need to keep a copy of the argument to be able to release it later. */
- g_assert (backup_args_pos < state->n_backup_args);
- state->backup_args[backup_args_pos] = *state->args[i];
- backup_args_pos += 1;
- }
-
- if (arg_type_tag == GI_TYPE_TAG_ARRAY) {
- GArray *array;
- gssize length_arg_pos;
-
- array = state->args[i]->v_pointer;
-
- length_arg_pos = g_type_info_get_array_length (state->arg_type_infos[i]);
- if (length_arg_pos >= 0) {
- int len = 0;
- /* Set the auxiliary argument holding the length. */
- if (array)
- len = array->len;
-
- state->args[length_arg_pos]->v_size = len;
- }
-
- /* Get rid of the GArray. */
- if ( (array != NULL) &&
- (g_type_info_get_array_type (state->arg_type_infos[i]) == GI_ARRAY_TYPE_C)) {
- 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. */
- g_array_free (array, FALSE);
- }
- }
- }
-
- py_args_pos += 1;
- }
- }
-
- g_assert (py_args_pos == state->n_py_args);
- g_assert (backup_args_pos == state->n_backup_args);
- }
-
- return TRUE;
-}
static inline gboolean
_invoke_function (PyGIInvokeState *state,
@@ -595,321 +69,6 @@ _invoke_function (PyGIInvokeState *state,
return TRUE;
}
-static gboolean
-_process_invocation_state (struct invocation_state *state,
- GIFunctionInfo *function_info, PyObject *py_args)
-{
- gsize i;
-
- /* Convert the return value. */
- if (state->is_constructor) {
- PyTypeObject *py_type;
- GIBaseInfo *info;
- GIInfoType info_type;
- GITransfer transfer;
-
- if (state->return_arg.v_pointer == NULL) {
- PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
- return FALSE;
- }
-
- g_assert (state->n_py_args > 0);
- py_type = (PyTypeObject *) PyTuple_GET_ITEM (py_args, 0);
-
- 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 *) function_info);
-
- switch (info_type) {
- case GI_INFO_TYPE_UNION:
- case GI_INFO_TYPE_STRUCT:
- {
- GType type;
-
- type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
-
- if (g_type_is_a (type, G_TYPE_BOXED)) {
- g_warn_if_fail (transfer == GI_TRANSFER_EVERYTHING);
- state->return_value = _pygi_boxed_new (py_type, state->return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING);
- } else if (type == G_TYPE_NONE && g_struct_info_is_foreign (info)) {
- state->return_value =
- pygi_struct_foreign_convert_from_g_argument (
- state->return_type_info, state->return_arg.v_pointer);
- } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
- if (transfer != GI_TRANSFER_NOTHING)
- g_warning ("Return argument in %s returns a struct "
- "with a transfer mode of \"full\" "
- "Transfer mode should be set to None for "
- "struct types as there is no way to free "
- "them safely. Ignoring transfer mode "
- "to prevent a potential invalid free. "
- "This may cause a leak in your application.",
- g_base_info_get_name ( (GIBaseInfo *) function_info) );
-
- state->return_value = _pygi_struct_new (py_type, state->return_arg.v_pointer, FALSE);
- } else {
- PyErr_Format (PyExc_TypeError, "cannot create '%s' instances", py_type->tp_name);
- g_base_info_unref (info);
- return FALSE;
- }
-
- break;
- }
- case GI_INFO_TYPE_OBJECT:
- if (state->return_arg.v_pointer == NULL) {
- PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
- break;
- }
- 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 (state->return_arg.v_pointer);
- }
- break;
- default:
- /* Other types don't have neither methods nor constructors. */
- g_assert_not_reached();
- }
-
- g_base_info_unref (info);
-
- if (state->return_value == NULL) {
- /* TODO: release arguments. */
- return FALSE;
- }
- } else {
- GITransfer transfer;
-
- if ( (state->return_type_tag == GI_TYPE_TAG_ARRAY) &&
- (g_type_info_get_array_type (state->return_type_info) == GI_ARRAY_TYPE_C)) {
- /* Create a #GArray. */
- 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 *) function_info);
-
- state->return_value = _pygi_argument_to_object (&state->return_arg, state->return_type_info, transfer);
- if (state->return_value == NULL) {
- /* TODO: release argument. */
- return FALSE;
- }
-
- _pygi_argument_release (&state->return_arg, state->return_type_info, transfer, GI_DIRECTION_OUT);
-
- if (state->return_type_tag == GI_TYPE_TAG_ARRAY
- && transfer == GI_TRANSFER_NOTHING) {
- /* We created a #GArray, so free it. */
- state->return_arg.v_pointer = g_array_free (state->return_arg.v_pointer, FALSE);
- }
- }
-
- /* Convert output arguments and release arguments. */
- {
- gsize return_values_pos;
-
- return_values_pos = 0;
-
- if (state->n_return_values > 1) {
- /* Return a tuple. */
- PyObject *return_values;
-
- return_values = PyTuple_New (state->n_return_values);
- if (return_values == NULL) {
- /* TODO: release arguments. */
- return FALSE;
- }
-
- if (state->return_type_tag == GI_TYPE_TAG_VOID) {
- /* The current return value is None. */
- Py_DECREF (state->return_value);
- } else {
- /* Put the return value first. */
- g_assert (state->return_value != NULL);
- PyTuple_SET_ITEM (return_values, return_values_pos, state->return_value);
- return_values_pos += 1;
- }
-
- state->return_value = return_values;
- }
-
- for (i = 0; i < state->n_args; i++) {
- GIDirection direction;
- GITypeTag type_tag;
- GITransfer transfer;
-
- if (state->args_is_auxiliary[i]) {
- /* Auxiliary arguments are handled at the same time as their relatives. */
- continue;
- }
-
- 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 (state->arg_type_infos[i]);
-
- if ( (type_tag == GI_TYPE_TAG_ARRAY) &&
- (g_type_info_get_array_type (state->arg_type_infos[i]) == GI_ARRAY_TYPE_C) &&
- (direction != GI_DIRECTION_IN || transfer == GI_TRANSFER_NOTHING)) {
- /* Create a #GArray. */
- 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;
-
- /* If we created it, deallocate when it goes out of scope
- * otherwise it is unsafe to deallocate random structures
- * we are given
- */
- if (type_tag == GI_TYPE_TAG_INTERFACE) {
- GIBaseInfo *info;
- GIInfoType info_type;
-
- info = g_type_info_get_interface (state->arg_type_infos[i]);
- g_assert (info != NULL);
- info_type = g_base_info_get_type (info);
-
- if ( (info_type == GI_INFO_TYPE_STRUCT) &&
- !g_struct_info_is_foreign((GIStructInfo *) info) ) {
- if (g_arg_info_is_caller_allocates (state->arg_infos[i])) {
- transfer = GI_TRANSFER_EVERYTHING;
- } else if (transfer == GI_TRANSFER_EVERYTHING) {
- transfer = GI_TRANSFER_NOTHING;
- g_warning ("Out argument %ld in %s returns a struct "
- "with a transfer mode of \"full\". "
- "Transfer mode should be set to \"none\" for "
- "struct type returns as there is no way to free "
- "them safely. Ignoring transfer mode "
- "to prevent a potential invalid free. "
- "This may cause a leak in your application.",
- i, g_base_info_get_name ( (GIBaseInfo *) function_info) );
- }
- }
- }
-
- obj = _pygi_argument_to_object (state->args[i], state->arg_type_infos[i], transfer);
- if (obj == NULL) {
- /* TODO: release arguments. */
- return FALSE;
- }
-
- g_assert (return_values_pos < state->n_return_values);
-
- 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 (state->return_value);
- state->return_value = obj;
- }
-
- return_values_pos += 1;
- }
-
- }
-
- g_assert (state->n_return_values <= 1 || return_values_pos == state->n_return_values);
- }
-
- return TRUE;
-}
-
-static void
-_free_invocation_state (struct invocation_state *state)
-{
- gsize i;
- gsize backup_args_pos;
-
- 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);
- }
-
- /* release all arguments. */
- backup_args_pos = 0;
- for (i = 0; i < state->n_args; i++) {
-
- if (state->args_is_auxiliary[i]) {
- /* Auxiliary arguments are not released. */
- continue;
- }
-
- if (state->arg_infos[i] != NULL
- && state->arg_type_infos[i] != NULL) {
- GIDirection direction;
- GITypeTag type_tag;
- GITransfer transfer;
-
- direction = g_arg_info_get_direction (state->arg_infos[i]);
- transfer = g_arg_info_get_ownership_transfer (state->arg_infos[i]);
-
- /* Release the argument. */
- if (direction == GI_DIRECTION_INOUT) {
- if (state->args != NULL) {
- _pygi_argument_release (&state->backup_args[backup_args_pos],
- state->arg_type_infos[i],
- transfer, GI_DIRECTION_IN);
- }
- backup_args_pos += 1;
- }
- if (state->args != NULL && state->args[i] != NULL) {
- _pygi_argument_release (state->args[i], state->arg_type_infos[i],
- transfer, direction);
-
- 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)) {
- /* We created a #GArray and it has not been released above, so free it. */
- state->args[i]->v_pointer = g_array_free (state->args[i]->v_pointer, FALSE);
- }
- }
-
- }
-
- if (state->arg_type_infos[i] != NULL)
- g_base_info_unref ( (GIBaseInfo *) state->arg_type_infos[i]);
- if (state->arg_infos[i] != NULL)
- g_base_info_unref ( (GIBaseInfo *) state->arg_infos[i]);
- }
- g_assert (backup_args_pos == state->n_backup_args);
-
- g_slice_free1 (sizeof (gpointer) * state->n_args, state->arg_infos);
- g_slice_free1 (sizeof (gpointer) * state->n_args, state->arg_type_infos);
- g_slice_free1 (sizeof (gboolean) * state->n_args, state->args_is_auxiliary);
-
- if (state->args != NULL) {
- g_slice_free1 (sizeof (gpointer) * state->n_args, state->args);
- }
-
- if (state->in_args != NULL) {
- g_slice_free1 (sizeof (GIArgument) * state->n_in_args, state->in_args);
- }
-
- if (state->out_args != NULL) {
- g_slice_free1 (sizeof (GIArgument) * state->n_out_args, state->out_args);
- }
-
- if (state->out_values != NULL) {
- g_slice_free1 (sizeof (GIArgument) * state->n_out_args, state->out_values);
- }
-
- if (state->backup_args != NULL) {
- g_slice_free1 (sizeof (GIArgument) * state->n_backup_args, state->backup_args);
- }
-
- if (PyErr_Occurred()) {
- Py_CLEAR (state->return_value);
- }
-}
-
static inline gboolean
_invoke_state_init_from_function_cache(PyGIInvokeState *state,
PyGIFunctionCache *cache,
diff --git a/gi/pygi-marshal.c b/gi/pygi-marshal.c
index fa744f3..812caca 100644
--- a/gi/pygi-marshal.c
+++ b/gi/pygi-marshal.c
@@ -32,1966 +32,6 @@
#include "pygi-cache.h"
-static void
-_pygi_g_type_tag_py_bounds (GITypeTag type_tag,
- PyObject **lower,
- PyObject **upper)
-{
- switch (type_tag) {
- case GI_TYPE_TAG_INT8:
- *lower = PYGLIB_PyLong_FromLong (-128);
- *upper = PYGLIB_PyLong_FromLong (127);
- break;
- case GI_TYPE_TAG_UINT8:
- *upper = PYGLIB_PyLong_FromLong (255);
- *lower = PYGLIB_PyLong_FromLong (0);
- break;
- case GI_TYPE_TAG_INT16:
- *lower = PYGLIB_PyLong_FromLong (-32768);
- *upper = PYGLIB_PyLong_FromLong (32767);
- break;
- case GI_TYPE_TAG_UINT16:
- *upper = PYGLIB_PyLong_FromLong (65535);
- *lower = PYGLIB_PyLong_FromLong (0);
- break;
- case GI_TYPE_TAG_INT32:
- *lower = PYGLIB_PyLong_FromLong (G_MININT32);
- *upper = PYGLIB_PyLong_FromLong (G_MAXINT32);
- break;
- case GI_TYPE_TAG_UINT32:
- /* Note: On 32-bit archs, this number doesn't fit in a long. */
- *upper = PyLong_FromLongLong (G_MAXUINT32);
- *lower = PYGLIB_PyLong_FromLong (0);
- break;
- case GI_TYPE_TAG_INT64:
- /* Note: On 32-bit archs, these numbers don't fit in a long. */
- *lower = PyLong_FromLongLong (G_MININT64);
- *upper = PyLong_FromLongLong (G_MAXINT64);
- break;
- case GI_TYPE_TAG_UINT64:
- *upper = PyLong_FromUnsignedLongLong (G_MAXUINT64);
- *lower = PYGLIB_PyLong_FromLong (0);
- break;
- case GI_TYPE_TAG_FLOAT:
- *upper = PyFloat_FromDouble (G_MAXFLOAT);
- *lower = PyFloat_FromDouble (-G_MAXFLOAT);
- break;
- case GI_TYPE_TAG_DOUBLE:
- *upper = PyFloat_FromDouble (G_MAXDOUBLE);
- *lower = PyFloat_FromDouble (-G_MAXDOUBLE);
- break;
- default:
- PyErr_SetString (PyExc_TypeError, "Non-numeric type tag");
- *lower = *upper = NULL;
- return;
- }
-}
-
-gint
-_pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
- gboolean is_instance,
- PyObject *object)
-{
- gint retval;
-
- GType g_type;
- PyObject *py_type;
- gchar *type_name_expected = NULL;
- GIInfoType interface_type;
-
- interface_type = g_base_info_get_type (info);
- if ( (interface_type == GI_INFO_TYPE_STRUCT) &&
- (g_struct_info_is_foreign ( (GIStructInfo*) info))) {
- /* TODO: Could we check is the correct foreign type? */
- return 1;
- }
-
- g_type = g_registered_type_info_get_g_type (info);
- if (g_type != G_TYPE_NONE) {
- py_type = _pygi_type_get_from_g_type (g_type);
- } else {
- py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info);
- }
-
- if (py_type == NULL) {
- return 0;
- }
-
- g_assert (PyType_Check (py_type));
-
- if (is_instance) {
- retval = PyObject_IsInstance (object, py_type);
- if (!retval) {
- type_name_expected = _pygi_g_base_info_get_fullname (
- (GIBaseInfo *) info);
- }
- } else {
- if (!PyObject_Type (py_type)) {
- type_name_expected = "type";
- retval = 0;
- } else if (!PyType_IsSubtype ( (PyTypeObject *) object,
- (PyTypeObject *) py_type)) {
- type_name_expected = _pygi_g_base_info_get_fullname (
- (GIBaseInfo *) info);
- retval = 0;
- } else {
- retval = 1;
- }
- }
-
- Py_DECREF (py_type);
-
- if (!retval) {
- PyTypeObject *object_type;
-
- if (type_name_expected == NULL) {
- return -1;
- }
-
- object_type = (PyTypeObject *) PyObject_Type (object);
- if (object_type == NULL) {
- return -1;
- }
-
- PyErr_Format (PyExc_TypeError, "Must be %s, not %s",
- type_name_expected, object_type->tp_name);
-
- g_free (type_name_expected);
- }
-
- return retval;
-}
-
-gint
-_pygi_g_type_interface_check_object (GIBaseInfo *info,
- PyObject *object)
-{
- gint retval = 1;
- GIInfoType info_type;
-
- info_type = g_base_info_get_type (info);
- switch (info_type) {
- case GI_INFO_TYPE_CALLBACK:
- if (!PyCallable_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- case GI_INFO_TYPE_ENUM:
- retval = 0;
- if (PyNumber_Check (object)) {
- PyObject *number = PYGLIB_PyNumber_Long (object);
- if (number == NULL)
- PyErr_Clear();
- else {
- glong value = PYGLIB_PyLong_AsLong (number);
- int i;
- for (i = 0; i < g_enum_info_get_n_values (info); i++) {
- GIValueInfo *value_info = g_enum_info_get_value (info, i);
- glong enum_value = g_value_info_get_value (value_info);
- if (value == enum_value) {
- retval = 1;
- break;
- }
- }
- }
- }
- if (retval < 1)
- retval = _pygi_g_registered_type_info_check_object (
- (GIRegisteredTypeInfo *) info, TRUE, object);
- break;
- case GI_INFO_TYPE_FLAGS:
- if (PyNumber_Check (object)) {
- /* Accept 0 as a valid flag value */
- PyObject *number = PYGLIB_PyNumber_Long (object);
- if (number == NULL)
- PyErr_Clear();
- else {
- long value = PYGLIB_PyLong_AsLong (number);
- if (value == 0)
- break;
- else if (value == -1)
- PyErr_Clear();
- }
- }
- retval = _pygi_g_registered_type_info_check_object (
- (GIRegisteredTypeInfo *) info, TRUE, object);
- break;
- case GI_INFO_TYPE_STRUCT:
- {
- GType type;
-
- /* Handle special cases. */
- type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
- if (g_type_is_a (type, G_TYPE_CLOSURE)) {
- if (!PyCallable_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- } else if (g_type_is_a (type, G_TYPE_VALUE)) {
- /* we can't check g_values because we don't have
- * enough context so just pass them through */
- break;
- }
-
- /* Fallback. */
- }
- case GI_INFO_TYPE_BOXED:
- case GI_INFO_TYPE_INTERFACE:
- case GI_INFO_TYPE_OBJECT:
- case GI_INFO_TYPE_UNION:
- retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object);
- break;
- default:
- g_assert_not_reached();
- }
-
- return retval;
-}
-
-gint
-_pygi_g_type_info_check_object (GITypeInfo *type_info,
- PyObject *object,
- gboolean allow_none)
-{
- GITypeTag type_tag;
- gint retval = 1;
-
- if (allow_none && object == Py_None) {
- return retval;
- }
-
- type_tag = g_type_info_get_tag (type_info);
-
- switch (type_tag) {
- case GI_TYPE_TAG_VOID:
- /* No check; VOID means undefined type */
- break;
- case GI_TYPE_TAG_BOOLEAN:
- /* No check; every Python object has a truth value. */
- break;
- case GI_TYPE_TAG_UINT8:
- /* UINT8 types can be characters */
- if (PYGLIB_PyBytes_Check(object)) {
- if (PYGLIB_PyBytes_Size(object) != 1) {
- PyErr_Format (PyExc_TypeError, "Must be a single character");
- retval = 0;
- break;
- }
-
- break;
- }
- case GI_TYPE_TAG_INT8:
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_INT32:
- case GI_TYPE_TAG_UINT32:
- case GI_TYPE_TAG_INT64:
- case GI_TYPE_TAG_UINT64:
- case GI_TYPE_TAG_FLOAT:
- case GI_TYPE_TAG_DOUBLE:
- {
- PyObject *number, *lower, *upper;
-
- if (!PyNumber_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be number, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- if (type_tag == GI_TYPE_TAG_FLOAT || type_tag == GI_TYPE_TAG_DOUBLE) {
- number = PyNumber_Float (object);
- } else {
- number = PYGLIB_PyNumber_Long (object);
- }
-
- _pygi_g_type_tag_py_bounds (type_tag, &lower, &upper);
-
- if (lower == NULL || upper == NULL || number == NULL) {
- retval = -1;
- goto check_number_release;
- }
-
- /* Check bounds */
- if (PyObject_RichCompareBool (lower, number, Py_GT)
- || PyObject_RichCompareBool (upper, number, Py_LT)) {
- PyObject *lower_str;
- PyObject *upper_str;
-
- if (PyErr_Occurred()) {
- retval = -1;
- goto check_number_release;
- }
-
- lower_str = PyObject_Str (lower);
- upper_str = PyObject_Str (upper);
- if (lower_str == NULL || upper_str == NULL) {
- retval = -1;
- goto check_number_error_release;
- }
-
-#if PY_VERSION_HEX < 0x03000000
- PyErr_Format (PyExc_ValueError, "Must range from %s to %s",
- PyString_AS_STRING (lower_str),
- PyString_AS_STRING (upper_str));
-#else
- {
- PyObject *lower_pybytes_obj = PyUnicode_AsUTF8String (lower_str);
- if (!lower_pybytes_obj)
- goto utf8_fail;
-
- PyObject *upper_pybytes_obj = PyUnicode_AsUTF8String (upper_str);
- if (!upper_pybytes_obj) {
- Py_DECREF(lower_pybytes_obj);
- goto utf8_fail;
- }
-
- PyErr_Format (PyExc_ValueError, "Must range from %s to %s",
- PyBytes_AsString (lower_pybytes_obj),
- PyBytes_AsString (upper_pybytes_obj));
- Py_DECREF (lower_pybytes_obj);
- Py_DECREF (upper_pybytes_obj);
- }
-utf8_fail:
-#endif
- retval = 0;
-
-check_number_error_release:
- Py_XDECREF (lower_str);
- Py_XDECREF (upper_str);
- }
-
-check_number_release:
- Py_XDECREF (number);
- Py_XDECREF (lower);
- Py_XDECREF (upper);
- break;
- }
- case GI_TYPE_TAG_GTYPE:
- {
- if (pyg_type_from_object (object) == 0) {
- PyErr_Format (PyExc_TypeError, "Must be gobject.GType, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- }
- case GI_TYPE_TAG_UNICHAR:
- {
- Py_ssize_t size;
- if (PyUnicode_Check (object)) {
- size = PyUnicode_GET_SIZE (object);
-#if PY_VERSION_HEX < 0x03000000
- } else if (PyString_Check (object)) {
- PyObject *pyuni = PyUnicode_FromEncodedObject (object, "UTF-8", "strict");
- size = PyUnicode_GET_SIZE (pyuni);
- Py_DECREF(pyuni);
-#endif
- } else {
- PyErr_Format (PyExc_TypeError, "Must be string, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- if (size != 1) {
- PyErr_Format (PyExc_TypeError, "Must be a one character string, not %ld characters",
- size);
- retval = 0;
- break;
- }
-
- break;
- }
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- if (!PYGLIB_PyBaseString_Check (object) ) {
- PyErr_Format (PyExc_TypeError, "Must be string, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- case GI_TYPE_TAG_ARRAY:
- {
- gssize fixed_size;
- Py_ssize_t length;
- GITypeInfo *item_type_info;
- Py_ssize_t i;
-
- if (!PySequence_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- length = PySequence_Length (object);
- if (length < 0) {
- retval = -1;
- break;
- }
-
- fixed_size = g_type_info_get_array_fixed_size (type_info);
- if (fixed_size >= 0 && length != fixed_size) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- fixed_size, length);
- retval = 0;
- break;
- }
-
- item_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (item_type_info != NULL);
-
- /* FIXME: This is insain. We really should only check the first
- * object and perhaps have a debugging mode. Large arrays
- * will cause apps to slow to a crawl.
- */
- for (i = 0; i < length; i++) {
- PyObject *item;
-
- item = PySequence_GetItem (object, i);
- if (item == NULL) {
- retval = -1;
- break;
- }
-
- retval = _pygi_g_type_info_check_object (item_type_info, item, TRUE);
-
- Py_DECREF (item);
-
- if (retval < 0) {
- break;
- }
- if (!retval) {
- _PyGI_ERROR_PREFIX ("Item %zd: ", i);
- break;
- }
- }
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
-
- break;
- }
- case GI_TYPE_TAG_INTERFACE:
- {
- GIBaseInfo *info;
-
- info = g_type_info_get_interface (type_info);
- g_assert (info != NULL);
-
- retval = _pygi_g_type_interface_check_object(info, object);
-
- g_base_info_unref (info);
- break;
- }
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- {
- Py_ssize_t length;
- GITypeInfo *item_type_info;
- Py_ssize_t i;
-
- if (!PySequence_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- length = PySequence_Length (object);
- if (length < 0) {
- retval = -1;
- break;
- }
-
- item_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (item_type_info != NULL);
-
- for (i = 0; i < length; i++) {
- PyObject *item;
-
- item = PySequence_GetItem (object, i);
- if (item == NULL) {
- retval = -1;
- break;
- }
-
- retval = _pygi_g_type_info_check_object (item_type_info, item, TRUE);
-
- Py_DECREF (item);
-
- if (retval < 0) {
- break;
- }
- if (!retval) {
- _PyGI_ERROR_PREFIX ("Item %zd: ", i);
- break;
- }
- }
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
- break;
- }
- case GI_TYPE_TAG_GHASH:
- {
- Py_ssize_t length;
- PyObject *keys;
- PyObject *values;
- GITypeInfo *key_type_info;
- GITypeInfo *value_type_info;
- Py_ssize_t i;
-
- keys = PyMapping_Keys (object);
- if (keys == NULL) {
- PyErr_Format (PyExc_TypeError, "Must be mapping, not %s",
- object->ob_type->tp_name);
- retval = 0;
- break;
- }
-
- length = PyMapping_Length (object);
- if (length < 0) {
- Py_DECREF (keys);
- retval = -1;
- break;
- }
-
- values = PyMapping_Values (object);
- if (values == NULL) {
- retval = -1;
- Py_DECREF (keys);
- break;
- }
-
- key_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (key_type_info != NULL);
-
- value_type_info = g_type_info_get_param_type (type_info, 1);
- g_assert (value_type_info != NULL);
-
- for (i = 0; i < length; i++) {
- PyObject *key;
- PyObject *value;
-
- key = PyList_GET_ITEM (keys, i);
- value = PyList_GET_ITEM (values, i);
-
- retval = _pygi_g_type_info_check_object (key_type_info, key, TRUE);
- if (retval < 0) {
- break;
- }
- if (!retval) {
- _PyGI_ERROR_PREFIX ("Key %zd :", i);
- break;
- }
-
- retval = _pygi_g_type_info_check_object (value_type_info, value, TRUE);
- if (retval < 0) {
- break;
- }
- if (!retval) {
- _PyGI_ERROR_PREFIX ("Value %zd :", i);
- break;
- }
- }
-
- g_base_info_unref ( (GIBaseInfo *) key_type_info);
- g_base_info_unref ( (GIBaseInfo *) value_type_info);
- Py_DECREF (values);
- Py_DECREF (keys);
- break;
- }
- case GI_TYPE_TAG_ERROR:
- PyErr_SetString (PyExc_NotImplementedError, "Error marshalling is not supported yet");
- /* TODO */
- break;
- }
-
- return retval;
-}
-
-GArray *
-_pygi_argument_to_array (GIArgument *arg,
- GIArgument *args[],
- GITypeInfo *type_info,
- gboolean is_method)
-{
- GITypeInfo *item_type_info;
- gboolean is_zero_terminated;
- gsize item_size;
- gssize length;
- GArray *g_array;
-
- if (arg->v_pointer == NULL) {
- return NULL;
- }
-
- is_zero_terminated = g_type_info_is_zero_terminated (type_info);
- item_type_info = g_type_info_get_param_type (type_info, 0);
-
- item_size = _pygi_g_type_info_size (item_type_info);
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
-
- if (is_zero_terminated) {
- length = g_strv_length (arg->v_pointer);
- } else {
- length = g_type_info_get_array_fixed_size (type_info);
- if (length < 0) {
- gint length_arg_pos;
-
- length_arg_pos = g_type_info_get_array_length (type_info);
- g_assert (length_arg_pos >= 0);
-
- /* FIXME: Take into account the type of the argument. */
- length = args[length_arg_pos]->v_int;
- }
- }
-
- g_assert (length >= 0);
-
- g_array = g_array_new (is_zero_terminated, FALSE, item_size);
-
- g_array->data = arg->v_pointer;
- g_array->len = length;
-
- return g_array;
-}
-
-GIArgument
-_pygi_argument_from_object (PyObject *object,
- GITypeInfo *type_info,
- GITransfer transfer)
-{
- GIArgument arg;
- GITypeTag type_tag;
-
- memset(&arg, 0, sizeof(GIArgument));
- type_tag = g_type_info_get_tag (type_info);
-
- switch (type_tag) {
- case GI_TYPE_TAG_VOID:
- g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
- arg.v_pointer = object;
- break;
- case GI_TYPE_TAG_BOOLEAN:
- {
- arg.v_boolean = PyObject_IsTrue (object);
- break;
- }
- case GI_TYPE_TAG_UINT8:
- if (PYGLIB_PyBytes_Check(object)) {
- arg.v_long = (long)(PYGLIB_PyBytes_AsString(object)[0]);
- break;
- }
-
- case GI_TYPE_TAG_INT8:
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_INT32:
- {
- PyObject *int_;
-
- int_ = PYGLIB_PyNumber_Long (object);
- if (int_ == NULL) {
- break;
- }
-
- arg.v_long = PYGLIB_PyLong_AsLong (int_);
-
- Py_DECREF (int_);
-
- break;
- }
- case GI_TYPE_TAG_UINT32:
- case GI_TYPE_TAG_UINT64:
- {
- PyObject *number;
- guint64 value;
-
- number = PYGLIB_PyNumber_Long (object);
- if (number == NULL) {
- break;
- }
-
-#if PY_VERSION_HEX < 0x03000000
- if (PyInt_Check (number)) {
- value = PyInt_AS_LONG (number);
- } else
-#endif
- value = PyLong_AsUnsignedLongLong (number);
-
- arg.v_uint64 = value;
-
- Py_DECREF (number);
-
- break;
- }
- case GI_TYPE_TAG_INT64:
- {
- PyObject *number;
- gint64 value;
-
- number = PYGLIB_PyNumber_Long (object);
- if (number == NULL) {
- break;
- }
-
-#if PY_VERSION_HEX < 0x03000000
- if (PyInt_Check (number)) {
- value = PyInt_AS_LONG (number);
- } else
-#endif
- value = PyLong_AsLongLong (number);
-
- arg.v_int64 = value;
-
- Py_DECREF (number);
-
- break;
- }
- case GI_TYPE_TAG_FLOAT:
- {
- PyObject *float_;
-
- float_ = PyNumber_Float (object);
- if (float_ == NULL) {
- break;
- }
-
- arg.v_float = (float) PyFloat_AsDouble (float_);
- Py_DECREF (float_);
-
- break;
- }
- case GI_TYPE_TAG_DOUBLE:
- {
- PyObject *float_;
-
- float_ = PyNumber_Float (object);
- if (float_ == NULL) {
- break;
- }
-
- arg.v_double = PyFloat_AsDouble (float_);
- Py_DECREF (float_);
-
- break;
- }
- case GI_TYPE_TAG_GTYPE:
- {
- arg.v_long = pyg_type_from_object (object);
-
- break;
- }
- case GI_TYPE_TAG_UNICHAR:
- {
- gchar *string;
-
- if (object == Py_None) {
- arg.v_uint32 = 0;
- break;
- }
-
-#if PY_VERSION_HEX < 0x03000000
- if (PyUnicode_Check(object)) {
- PyObject *pystr_obj = PyUnicode_AsUTF8String (object);
-
- if (!pystr_obj)
- break;
-
- string = g_strdup(PyString_AsString (pystr_obj));
- Py_DECREF(pystr_obj);
- } else {
- string = g_strdup(PyString_AsString (object));
- }
-#else
- {
- PyObject *pybytes_obj = PyUnicode_AsUTF8String (object);
- if (!pybytes_obj)
- break;
-
- string = g_strdup(PyBytes_AsString (pybytes_obj));
- Py_DECREF (pybytes_obj);
- }
-#endif
-
- arg.v_uint32 = g_utf8_get_char (string);
-
- break;
- }
- case GI_TYPE_TAG_UTF8:
- {
- gchar *string;
-
- if (object == Py_None) {
- arg.v_string = NULL;
- break;
- }
-#if PY_VERSION_HEX < 0x03000000
- if (PyUnicode_Check(object)) {
- PyObject *pystr_obj = PyUnicode_AsUTF8String (object);
-
- if (!pystr_obj)
- break;
-
- string = g_strdup(PyString_AsString (pystr_obj));
- Py_DECREF(pystr_obj);
- } else {
- string = g_strdup(PyString_AsString (object));
- }
-#else
- {
- PyObject *pybytes_obj = PyUnicode_AsUTF8String (object);
- if (!pybytes_obj)
- break;
-
- string = g_strdup(PyBytes_AsString (pybytes_obj));
- Py_DECREF (pybytes_obj);
- }
-#endif
- arg.v_string = string;
-
- break;
- }
- case GI_TYPE_TAG_FILENAME:
- {
- GError *error = NULL;
- gchar *string;
-
-#if PY_VERSION_HEX < 0x03000000
- string = g_strdup(PyString_AsString (object));
-#else
- {
- PyObject *pybytes_obj = PyUnicode_AsUTF8String (object);
- if (!pybytes_obj)
- break;
-
- string = g_strdup(PyBytes_AsString (pybytes_obj));
- Py_DECREF (pybytes_obj);
- }
-#endif
-
- if (string == NULL) {
- break;
- }
-
- arg.v_string = g_filename_from_utf8 (string, -1, NULL, NULL, &error);
- g_free(string);
-
- if (arg.v_string == NULL) {
- PyErr_SetString (PyExc_Exception, error->message);
- /* TODO: Convert the error to an exception. */
- }
-
- break;
- }
- case GI_TYPE_TAG_ARRAY:
- {
- Py_ssize_t length;
- gboolean is_zero_terminated;
- GITypeInfo *item_type_info;
- gsize item_size;
- GArray *array;
- GITransfer item_transfer;
- Py_ssize_t i;
-
- if (object == Py_None) {
- arg.v_pointer = NULL;
- break;
- }
-
- length = PySequence_Length (object);
- if (length < 0) {
- break;
- }
-
- is_zero_terminated = g_type_info_is_zero_terminated (type_info);
- item_type_info = g_type_info_get_param_type (type_info, 0);
-
- item_size = _pygi_g_type_info_size (item_type_info);
-
- array = g_array_sized_new (is_zero_terminated, FALSE, item_size, length);
- if (array == NULL) {
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
- PyErr_NoMemory();
- break;
- }
-
- if (g_type_info_get_tag (item_type_info) == GI_TYPE_TAG_UINT8 &&
- PYGLIB_PyBytes_Check(object)) {
-
- memcpy(array->data, PYGLIB_PyBytes_AsString(object), length);
- array->len = length;
- goto array_success;
- }
-
-
- item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
-
- for (i = 0; i < length; i++) {
- PyObject *py_item;
- GIArgument item;
-
- py_item = PySequence_GetItem (object, i);
- if (py_item == NULL) {
- goto array_item_error;
- }
-
- item = _pygi_argument_from_object (py_item, item_type_info, item_transfer);
-
- Py_DECREF (py_item);
-
- if (PyErr_Occurred()) {
- goto array_item_error;
- }
-
- g_array_insert_val (array, i, item);
- continue;
-
-array_item_error:
- /* Free everything we have converted so far. */
- _pygi_argument_release ( (GIArgument *) &array, type_info,
- GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
- array = NULL;
-
- _PyGI_ERROR_PREFIX ("Item %zd: ", i);
- break;
- }
-
-array_success:
- arg.v_pointer = array;
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
- break;
- }
- case GI_TYPE_TAG_INTERFACE:
- {
- GIBaseInfo *info;
- GIInfoType info_type;
-
- info = g_type_info_get_interface (type_info);
- info_type = g_base_info_get_type (info);
-
- switch (info_type) {
- case GI_INFO_TYPE_CALLBACK:
- /* This should be handled in invoke() */
- g_assert_not_reached();
- break;
- case GI_INFO_TYPE_BOXED:
- case GI_INFO_TYPE_STRUCT:
- case GI_INFO_TYPE_UNION:
- {
- GType type;
-
- if (object == Py_None) {
- arg.v_pointer = NULL;
- break;
- }
-
- type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
-
- /* Handle special cases first. */
- if (g_type_is_a (type, G_TYPE_VALUE)) {
- GValue *value;
- GType object_type;
- gint retval;
-
- object_type = pyg_type_from_object_strict ( (PyObject *) object->ob_type, FALSE);
- if (object_type == G_TYPE_INVALID) {
- PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
- break;
- }
-
- g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
-
- value = g_slice_new0 (GValue);
- g_value_init (value, object_type);
-
- retval = pyg_value_from_pyobject (value, object);
- if (retval < 0) {
- g_slice_free (GValue, value);
- PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
- break;
- }
-
- arg.v_pointer = value;
- } else if (g_type_is_a (type, G_TYPE_CLOSURE)) {
- GClosure *closure;
-
- g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
-
- closure = pyg_closure_new (object, NULL, NULL);
- if (closure == NULL) {
- PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
- break;
- }
-
- arg.v_pointer = closure;
- } else if (g_type_is_a (type, G_TYPE_BOXED)) {
- arg.v_pointer = pyg_boxed_get (object, void);
- if (transfer == GI_TRANSFER_EVERYTHING) {
- arg.v_pointer = g_boxed_copy (type, arg.v_pointer);
- }
- } else if ( (type == G_TYPE_NONE) && (g_struct_info_is_foreign (info))) {
- PyObject *result;
- result = pygi_struct_foreign_convert_to_g_argument (
- object, type_info, transfer, &arg);
- } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
- g_warn_if_fail (!g_type_info_is_pointer (type_info) || transfer == GI_TRANSFER_NOTHING);
- arg.v_pointer = pyg_pointer_get (object, void);
- } else {
- PyErr_Format (PyExc_NotImplementedError, "structure type '%s' is not supported yet", g_type_name (type));
- }
-
- break;
- }
- case GI_INFO_TYPE_ENUM:
- case GI_INFO_TYPE_FLAGS:
- {
- PyObject *int_;
-
- int_ = PYGLIB_PyNumber_Long (object);
- if (int_ == NULL) {
- break;
- }
-
- arg.v_long = PYGLIB_PyLong_AsLong (int_);
-
- Py_DECREF (int_);
-
- break;
- }
- case GI_INFO_TYPE_INTERFACE:
- case GI_INFO_TYPE_OBJECT:
- if (object == Py_None) {
- arg.v_pointer = NULL;
- break;
- }
-
- arg.v_pointer = pygobject_get (object);
- if (transfer == GI_TRANSFER_EVERYTHING) {
- g_object_ref (arg.v_pointer);
- }
-
- break;
- default:
- g_assert_not_reached();
- }
- g_base_info_unref (info);
- break;
- }
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- {
- Py_ssize_t length;
- GITypeInfo *item_type_info;
- GSList *list = NULL;
- GITransfer item_transfer;
- Py_ssize_t i;
-
- if (object == Py_None) {
- arg.v_pointer = NULL;
- break;
- }
-
- length = PySequence_Length (object);
- if (length < 0) {
- break;
- }
-
- item_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (item_type_info != NULL);
-
- item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
-
- for (i = length - 1; i >= 0; i--) {
- PyObject *py_item;
- GIArgument item;
-
- py_item = PySequence_GetItem (object, i);
- if (py_item == NULL) {
- goto list_item_error;
- }
-
- item = _pygi_argument_from_object (py_item, item_type_info, item_transfer);
-
- Py_DECREF (py_item);
-
- if (PyErr_Occurred()) {
- goto list_item_error;
- }
-
- if (type_tag == GI_TYPE_TAG_GLIST) {
- list = (GSList *) g_list_prepend ( (GList *) list, item.v_pointer);
- } else {
- list = g_slist_prepend (list, item.v_pointer);
- }
-
- continue;
-
-list_item_error:
- /* Free everything we have converted so far. */
- _pygi_argument_release ( (GIArgument *) &list, type_info,
- GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
- list = NULL;
-
- _PyGI_ERROR_PREFIX ("Item %zd: ", i);
- break;
- }
-
- arg.v_pointer = list;
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
-
- break;
- }
- case GI_TYPE_TAG_GHASH:
- {
- Py_ssize_t length;
- PyObject *keys;
- PyObject *values;
- GITypeInfo *key_type_info;
- GITypeInfo *value_type_info;
- GITypeTag key_type_tag;
- GHashFunc hash_func;
- GEqualFunc equal_func;
- GHashTable *hash_table;
- GITransfer item_transfer;
- Py_ssize_t i;
-
-
- if (object == Py_None) {
- arg.v_pointer = NULL;
- break;
- }
-
- length = PyMapping_Length (object);
- if (length < 0) {
- break;
- }
-
- keys = PyMapping_Keys (object);
- if (keys == NULL) {
- break;
- }
-
- values = PyMapping_Values (object);
- if (values == NULL) {
- Py_DECREF (keys);
- break;
- }
-
- key_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (key_type_info != NULL);
-
- value_type_info = g_type_info_get_param_type (type_info, 1);
- g_assert (value_type_info != NULL);
-
- key_type_tag = g_type_info_get_tag (key_type_info);
-
- switch (key_type_tag) {
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- hash_func = g_str_hash;
- equal_func = g_str_equal;
- break;
- default:
- hash_func = NULL;
- equal_func = NULL;
- }
-
- hash_table = g_hash_table_new (hash_func, equal_func);
- if (hash_table == NULL) {
- PyErr_NoMemory();
- goto hash_table_release;
- }
-
- item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
-
- for (i = 0; i < length; i++) {
- PyObject *py_key;
- PyObject *py_value;
- GIArgument key;
- GIArgument value;
-
- py_key = PyList_GET_ITEM (keys, i);
- py_value = PyList_GET_ITEM (values, i);
-
- key = _pygi_argument_from_object (py_key, key_type_info, item_transfer);
- if (PyErr_Occurred()) {
- goto hash_table_item_error;
- }
-
- value = _pygi_argument_from_object (py_value, value_type_info, item_transfer);
- if (PyErr_Occurred()) {
- _pygi_argument_release (&key, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
- goto hash_table_item_error;
- }
-
- g_hash_table_insert (hash_table, key.v_pointer, value.v_pointer);
- continue;
-
-hash_table_item_error:
- /* Free everything we have converted so far. */
- _pygi_argument_release ( (GIArgument *) &hash_table, type_info,
- GI_TRANSFER_NOTHING, GI_DIRECTION_IN);
- hash_table = NULL;
-
- _PyGI_ERROR_PREFIX ("Item %zd: ", i);
- break;
- }
-
- arg.v_pointer = hash_table;
-
-hash_table_release:
- g_base_info_unref ( (GIBaseInfo *) key_type_info);
- g_base_info_unref ( (GIBaseInfo *) value_type_info);
- Py_DECREF (keys);
- Py_DECREF (values);
- break;
- }
- case GI_TYPE_TAG_ERROR:
- PyErr_SetString (PyExc_NotImplementedError, "error marshalling is not supported yet");
- /* TODO */
- break;
- }
-
- return arg;
-}
-
-PyObject *
-_pygi_argument_to_object (GIArgument *arg,
- GITypeInfo *type_info,
- GITransfer transfer)
-{
- GITypeTag type_tag;
- PyObject *object = NULL;
-
- type_tag = g_type_info_get_tag (type_info);
- switch (type_tag) {
- case GI_TYPE_TAG_VOID:
- if (g_type_info_is_pointer (type_info)) {
- /* Raw Python objects are passed to void* args */
- g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
- object = arg->v_pointer;
- } else
- object = Py_None;
- Py_XINCREF (object);
- break;
- case GI_TYPE_TAG_BOOLEAN:
- {
- object = PyBool_FromLong (arg->v_boolean);
- break;
- }
- case GI_TYPE_TAG_INT8:
- {
- object = PYGLIB_PyLong_FromLong (arg->v_int8);
- break;
- }
- case GI_TYPE_TAG_UINT8:
- {
- object = PYGLIB_PyLong_FromLong (arg->v_uint8);
- break;
- }
- case GI_TYPE_TAG_INT16:
- {
- object = PYGLIB_PyLong_FromLong (arg->v_int16);
- break;
- }
- case GI_TYPE_TAG_UINT16:
- {
- object = PYGLIB_PyLong_FromLong (arg->v_uint16);
- break;
- }
- case GI_TYPE_TAG_INT32:
- {
- object = PYGLIB_PyLong_FromLong (arg->v_int32);
- break;
- }
- case GI_TYPE_TAG_UINT32:
- {
- object = PyLong_FromLongLong (arg->v_uint32);
- break;
- }
- case GI_TYPE_TAG_INT64:
- {
- object = PyLong_FromLongLong (arg->v_int64);
- break;
- }
- case GI_TYPE_TAG_UINT64:
- {
- object = PyLong_FromUnsignedLongLong (arg->v_uint64);
- break;
- }
- case GI_TYPE_TAG_FLOAT:
- {
- object = PyFloat_FromDouble (arg->v_float);
- break;
- }
- case GI_TYPE_TAG_DOUBLE:
- {
- object = PyFloat_FromDouble (arg->v_double);
- break;
- }
- case GI_TYPE_TAG_GTYPE:
- {
- object = pyg_type_wrapper_new ( (GType) arg->v_long);
- break;
- }
- case GI_TYPE_TAG_UNICHAR:
- {
- /* Preserve the bidirectional mapping between 0 and "" */
- if (arg->v_uint32 == 0) {
- object = PYGLIB_PyUnicode_FromString ("");
- } else if (g_unichar_validate (arg->v_uint32)) {
- gchar utf8[6];
- gint bytes;
-
- bytes = g_unichar_to_utf8 (arg->v_uint32, utf8);
- object = PYGLIB_PyUnicode_FromStringAndSize ((char*)utf8, bytes);
- } else {
- /* TODO: Convert the error to an exception. */
- PyErr_Format (PyExc_TypeError,
- "Invalid unicode codepoint %" G_GUINT32_FORMAT,
- arg->v_uint32);
- object = Py_None;
- Py_INCREF (object);
- }
- break;
- }
- case GI_TYPE_TAG_UTF8:
- if (arg->v_string == NULL) {
- object = Py_None;
- Py_INCREF (object);
- break;
- }
-
- object = PYGLIB_PyUnicode_FromString (arg->v_string);
- break;
- case GI_TYPE_TAG_FILENAME:
- {
- GError *error = NULL;
- gchar *string;
-
- if (arg->v_string == NULL) {
- object = Py_None;
- Py_INCREF (object);
- break;
- }
-
- string = g_filename_to_utf8 (arg->v_string, -1, NULL, NULL, &error);
- if (string == NULL) {
- PyErr_SetString (PyExc_Exception, error->message);
- /* TODO: Convert the error to an exception. */
- break;
- }
-
- object = PYGLIB_PyUnicode_FromString (string);
-
- g_free (string);
-
- break;
- }
- case GI_TYPE_TAG_ARRAY:
- {
- GArray *array;
- GITypeInfo *item_type_info;
- GITypeTag item_type_tag;
- GITransfer item_transfer;
- gsize i, item_size;
-
- array = arg->v_pointer;
-
- item_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (item_type_info != NULL);
-
- item_type_tag = g_type_info_get_tag (item_type_info);
- item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
-
- if (item_type_tag == GI_TYPE_TAG_UINT8) {
- /* Return as a byte array */
- if (arg->v_pointer == NULL) {
- object = PYGLIB_PyBytes_FromString ("");
- break;
- }
-
- object = PYGLIB_PyBytes_FromStringAndSize(array->data, array->len);
- break;
-
- } else {
- if (arg->v_pointer == NULL) {
- object = PyList_New (0);
- break;
- }
-
- object = PyList_New (array->len);
- if (object == NULL) {
- break;
- }
-
- }
- item_size = g_array_get_element_size (array);
-
- for (i = 0; i < array->len; i++) {
- GIArgument item;
- PyObject *py_item;
- gboolean is_struct = FALSE;
-
- if (item_type_tag == GI_TYPE_TAG_INTERFACE) {
- GIBaseInfo *iface_info = g_type_info_get_interface (item_type_info);
- switch (g_base_info_get_type (iface_info)) {
- case GI_INFO_TYPE_STRUCT:
- case GI_INFO_TYPE_BOXED:
- is_struct = TRUE;
- default:
- break;
- }
- g_base_info_unref ( (GIBaseInfo *) iface_info);
- }
-
- if (is_struct) {
- item.v_pointer = &_g_array_index (array, GIArgument, i);
- } else {
- memcpy (&item, &_g_array_index (array, GIArgument, i), item_size);
- }
-
- py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer);
- if (py_item == NULL) {
- Py_CLEAR (object);
- _PyGI_ERROR_PREFIX ("Item %zu: ", i);
- break;
- }
-
- PyList_SET_ITEM (object, i, py_item);
- }
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
- break;
- }
- case GI_TYPE_TAG_INTERFACE:
- {
- GIBaseInfo *info;
- GIInfoType info_type;
-
- info = g_type_info_get_interface (type_info);
- info_type = g_base_info_get_type (info);
-
- switch (info_type) {
- case GI_INFO_TYPE_CALLBACK:
- {
- /* There is no way we can support a callback return
- * as we are never sure if the callback was set from C
- * or Python. API that return callbacks are broken
- * so we print a warning and send back a None
- */
-
- g_warning ("You are trying to use an API which returns a callback."
- "Callback returns can not be supported. Returning None instead.");
- object = Py_None;
- Py_INCREF (object);
- break;
- }
- case GI_INFO_TYPE_BOXED:
- case GI_INFO_TYPE_STRUCT:
- case GI_INFO_TYPE_UNION:
- {
- GType type;
-
- if (arg->v_pointer == NULL) {
- object = Py_None;
- Py_INCREF (object);
- break;
- }
-
- type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
- if (g_type_is_a (type, G_TYPE_VALUE)) {
- object = pyg_value_as_pyobject (arg->v_pointer, FALSE);
- } else if (g_type_is_a (type, G_TYPE_BOXED)) {
- PyObject *py_type;
-
- py_type = _pygi_type_get_from_g_type (type);
- if (py_type == NULL)
- break;
-
- object = _pygi_boxed_new ( (PyTypeObject *) py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING);
-
- Py_DECREF (py_type);
- } else if (g_type_is_a (type, G_TYPE_POINTER)) {
- PyObject *py_type;
-
- py_type = _pygi_type_get_from_g_type (type);
-
- if (py_type == NULL || !PyType_IsSubtype ( (PyTypeObject *) type, &PyGIStruct_Type)) {
- g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
- object = pyg_pointer_new (type, arg->v_pointer);
- } else {
- object = _pygi_struct_new ( (PyTypeObject *) py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING);
- }
-
- Py_XDECREF (py_type);
- } else if ( (type == G_TYPE_NONE) && (g_struct_info_is_foreign (info))) {
- object = pygi_struct_foreign_convert_from_g_argument (type_info, arg->v_pointer);
- } else if (type == G_TYPE_NONE) {
- PyObject *py_type;
-
- py_type = _pygi_type_import_by_gi_info (info);
- if (py_type == NULL) {
- break;
- }
-
- /* Only structs created in invoke can be safely marked
- * GI_TRANSFER_EVERYTHING. Trust that invoke has
- * filtered correctly
- */
- object = _pygi_struct_new ( (PyTypeObject *) py_type, arg->v_pointer,
- transfer == GI_TRANSFER_EVERYTHING);
-
- Py_DECREF (py_type);
- } else {
- PyErr_Format (PyExc_NotImplementedError, "structure type '%s' is not supported yet", g_type_name (type));
- }
-
- break;
- }
- case GI_INFO_TYPE_ENUM:
- case GI_INFO_TYPE_FLAGS:
- {
- GType type;
-
- type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
-
- if (type == G_TYPE_NONE) {
- /* An enum with a GType of None is an enum without GType */
- PyObject *py_type = _pygi_type_import_by_gi_info (info);
- PyObject *py_args = NULL;
-
- if (!py_type)
- return NULL;
-
- py_args = PyTuple_New (1);
- if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (arg->v_long)) != 0) {
- Py_DECREF (py_args);
- Py_DECREF (py_type);
- return NULL;
- }
-
- object = PyObject_CallFunction (py_type, "l", arg->v_long);
-
- Py_DECREF (py_args);
- Py_DECREF (py_type);
-
- } else if (info_type == GI_INFO_TYPE_ENUM) {
- object = pyg_enum_from_gtype (type, arg->v_long);
- } else {
- object = pyg_flags_from_gtype (type, arg->v_long);
- }
-
- break;
- }
- case GI_INFO_TYPE_INTERFACE:
- case GI_INFO_TYPE_OBJECT:
- if (arg->v_pointer == NULL) {
- object = Py_None;
- Py_INCREF (object);
- break;
- }
- object = pygobject_new (arg->v_pointer);
- break;
- default:
- g_assert_not_reached();
- }
-
- g_base_info_unref (info);
- break;
- }
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- {
- GSList *list;
- gsize length;
- GITypeInfo *item_type_info;
- GITransfer item_transfer;
- gsize i;
-
- list = arg->v_pointer;
- length = g_slist_length (list);
-
- object = PyList_New (length);
- if (object == NULL) {
- break;
- }
-
- item_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (item_type_info != NULL);
-
- item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
-
- for (i = 0; list != NULL; list = g_slist_next (list), i++) {
- GIArgument item;
- PyObject *py_item;
-
- item.v_pointer = list->data;
-
- py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer);
- if (py_item == NULL) {
- Py_CLEAR (object);
- _PyGI_ERROR_PREFIX ("Item %zu: ", i);
- break;
- }
-
- PyList_SET_ITEM (object, i, py_item);
- }
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
- break;
- }
- case GI_TYPE_TAG_GHASH:
- {
- GITypeInfo *key_type_info;
- GITypeInfo *value_type_info;
- GITransfer item_transfer;
- GHashTableIter hash_table_iter;
- GIArgument key;
- GIArgument value;
-
- if (arg->v_pointer == NULL) {
- object = Py_None;
- Py_INCREF (object);
- break;
- }
-
- object = PyDict_New();
- if (object == NULL) {
- break;
- }
-
- key_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (key_type_info != NULL);
- g_assert (g_type_info_get_tag (key_type_info) != GI_TYPE_TAG_VOID);
-
- value_type_info = g_type_info_get_param_type (type_info, 1);
- g_assert (value_type_info != NULL);
- g_assert (g_type_info_get_tag (value_type_info) != GI_TYPE_TAG_VOID);
-
- item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
-
- g_hash_table_iter_init (&hash_table_iter, (GHashTable *) arg->v_pointer);
- while (g_hash_table_iter_next (&hash_table_iter, &key.v_pointer, &value.v_pointer)) {
- PyObject *py_key;
- PyObject *py_value;
- int retval;
-
- py_key = _pygi_argument_to_object (&key, key_type_info, item_transfer);
- if (py_key == NULL) {
- break;
- }
-
- py_value = _pygi_argument_to_object (&value, value_type_info, item_transfer);
- if (py_value == NULL) {
- Py_DECREF (py_key);
- break;
- }
-
- retval = PyDict_SetItem (object, py_key, py_value);
-
- Py_DECREF (py_key);
- Py_DECREF (py_value);
-
- if (retval < 0) {
- Py_CLEAR (object);
- break;
- }
- }
-
- g_base_info_unref ( (GIBaseInfo *) key_type_info);
- g_base_info_unref ( (GIBaseInfo *) value_type_info);
- break;
- }
- case GI_TYPE_TAG_ERROR:
- /* Errors should be handled in the invoke wrapper. */
- g_assert_not_reached();
- }
-
- return object;
-}
-
-void
-_pygi_argument_release (GIArgument *arg,
- GITypeInfo *type_info,
- GITransfer transfer,
- GIDirection direction)
-{
- GITypeTag type_tag;
- gboolean is_out = (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT);
-
- type_tag = g_type_info_get_tag (type_info);
-
- switch (type_tag) {
- case GI_TYPE_TAG_VOID:
- /* Don't do anything, it's transparent to the C side */
- break;
- case GI_TYPE_TAG_BOOLEAN:
- case GI_TYPE_TAG_INT8:
- case GI_TYPE_TAG_UINT8:
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_INT32:
- case GI_TYPE_TAG_UINT32:
- case GI_TYPE_TAG_INT64:
- case GI_TYPE_TAG_UINT64:
- case GI_TYPE_TAG_FLOAT:
- case GI_TYPE_TAG_DOUBLE:
- case GI_TYPE_TAG_GTYPE:
- case GI_TYPE_TAG_UNICHAR:
- break;
- case GI_TYPE_TAG_FILENAME:
- case GI_TYPE_TAG_UTF8:
- /* With allow-none support the string could be NULL */
- if ((arg->v_string != NULL &&
- (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING))
- || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) {
- g_free (arg->v_string);
- }
- break;
- case GI_TYPE_TAG_ARRAY:
- {
- GArray *array;
- gsize i;
-
- if (arg->v_pointer == NULL) {
- return;
- }
-
- array = arg->v_pointer;
-
- if ( (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING)
- || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) {
- GITypeInfo *item_type_info;
- GITransfer item_transfer;
-
- item_type_info = g_type_info_get_param_type (type_info, 0);
-
- item_transfer = direction == GI_DIRECTION_IN ? GI_TRANSFER_NOTHING : GI_TRANSFER_EVERYTHING;
-
- /* Free the items */
- for (i = 0; i < array->len; i++) {
- GIArgument *item;
- item = &_g_array_index (array, GIArgument, i);
- _pygi_argument_release (item, item_type_info, item_transfer, direction);
- }
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
- }
-
- if ( (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)
- || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) {
- g_array_free (array, TRUE);
- }
-
- break;
- }
- case GI_TYPE_TAG_INTERFACE:
- {
- GIBaseInfo *info;
- GIInfoType info_type;
-
- info = g_type_info_get_interface (type_info);
- info_type = g_base_info_get_type (info);
-
- switch (info_type) {
- case GI_INFO_TYPE_CALLBACK:
- /* TODO */
- break;
- case GI_INFO_TYPE_BOXED:
- case GI_INFO_TYPE_STRUCT:
- case GI_INFO_TYPE_UNION:
- {
- GType type;
-
- if (arg->v_pointer == NULL) {
- return;
- }
-
- type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
-
- if (g_type_is_a (type, G_TYPE_VALUE)) {
- GValue *value;
-
- value = arg->v_pointer;
-
- if ( (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING)
- || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) {
- g_value_unset (value);
- }
-
- if ( (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)
- || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) {
- g_slice_free (GValue, value);
- }
- } else if (g_type_is_a (type, G_TYPE_CLOSURE)) {
- if (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) {
- g_closure_unref (arg->v_pointer);
- }
- } else if (g_struct_info_is_foreign ( (GIStructInfo*) info)) {
- if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING) {
- pygi_struct_foreign_release (info, arg->v_pointer);
- }
- } else if (g_type_is_a (type, G_TYPE_BOXED)) {
- } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) {
- g_warn_if_fail (!g_type_info_is_pointer (type_info) || transfer == GI_TRANSFER_NOTHING);
- }
-
- break;
- }
- case GI_INFO_TYPE_ENUM:
- case GI_INFO_TYPE_FLAGS:
- break;
- case GI_INFO_TYPE_INTERFACE:
- case GI_INFO_TYPE_OBJECT:
- if (arg->v_pointer == NULL) {
- return;
- }
- if (is_out && transfer == GI_TRANSFER_EVERYTHING) {
- g_object_unref (arg->v_pointer);
- }
- break;
- default:
- g_assert_not_reached();
- }
-
- g_base_info_unref (info);
- break;
- }
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- {
- GSList *list;
-
- if (arg->v_pointer == NULL) {
- return;
- }
-
- list = arg->v_pointer;
-
- if ( (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING)
- || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) {
- GITypeInfo *item_type_info;
- GITransfer item_transfer;
- GSList *item;
-
- item_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (item_type_info != NULL);
-
- item_transfer = direction == GI_DIRECTION_IN ? GI_TRANSFER_NOTHING : GI_TRANSFER_EVERYTHING;
-
- /* Free the items */
- for (item = list; item != NULL; item = g_slist_next (item)) {
- _pygi_argument_release ( (GIArgument *) &item->data, item_type_info,
- item_transfer, direction);
- }
-
- g_base_info_unref ( (GIBaseInfo *) item_type_info);
- }
-
- if ( (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)
- || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) {
- if (type_tag == GI_TYPE_TAG_GLIST) {
- g_list_free ( (GList *) list);
- } else {
- /* type_tag == GI_TYPE_TAG_GSLIST */
- g_slist_free (list);
- }
- }
-
- break;
- }
- case GI_TYPE_TAG_GHASH:
- {
- GHashTable *hash_table;
-
- if (arg->v_pointer == NULL) {
- return;
- }
-
- hash_table = arg->v_pointer;
-
- if (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) {
- /* We created the table without a destroy function, so keys and
- * values need to be released. */
- GITypeInfo *key_type_info;
- GITypeInfo *value_type_info;
- GITransfer item_transfer;
- GHashTableIter hash_table_iter;
- gpointer key;
- gpointer value;
-
- key_type_info = g_type_info_get_param_type (type_info, 0);
- g_assert (key_type_info != NULL);
-
- value_type_info = g_type_info_get_param_type (type_info, 1);
- g_assert (value_type_info != NULL);
-
- if (direction == GI_DIRECTION_IN) {
- item_transfer = GI_TRANSFER_NOTHING;
- } else {
- item_transfer = GI_TRANSFER_EVERYTHING;
- }
-
- g_hash_table_iter_init (&hash_table_iter, hash_table);
- while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) {
- _pygi_argument_release ( (GIArgument *) &key, key_type_info,
- item_transfer, direction);
- _pygi_argument_release ( (GIArgument *) &value, value_type_info,
- item_transfer, direction);
- }
-
- g_base_info_unref ( (GIBaseInfo *) key_type_info);
- g_base_info_unref ( (GIBaseInfo *) value_type_info);
- } else if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_CONTAINER) {
- /* Be careful to avoid keys and values being freed if the
- * callee gave a destroy function. */
- g_hash_table_steal_all (hash_table);
- }
-
- if ( (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)
- || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) {
- g_hash_table_unref (hash_table);
- }
-
- break;
- }
- case GI_TYPE_TAG_ERROR:
- {
- GError *error;
-
- if (arg->v_pointer == NULL) {
- return;
- }
-
- error = * (GError **) arg->v_pointer;
-
- if (error != NULL) {
- g_error_free (error);
- }
-
- g_slice_free (GError *, arg->v_pointer);
- break;
- }
- }
-}
-
-void
-_pygi_argument_init (void)
-{
- PyDateTime_IMPORT;
- _pygobject_import();
-}
-
/*** argument marshaling and validating routines ***/
gboolean
@@ -3897,7 +1937,7 @@ _pygi_marshal_out_interface_object (PyGIInvokeState *state,
if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
g_object_unref (arg->v_pointer);
-
+
return py_obj;
}
diff --git a/gi/pygi-private.h b/gi/pygi-private.h
index 5b7b505..8b27778 100644
--- a/gi/pygi-private.h
+++ b/gi/pygi-private.h
@@ -29,12 +29,10 @@
#include "pygi-callbacks.h"
#include "pygi-property.h"
#include "pygi-signal-closure.h"
+#include "pygi-invoke.h"
#ifdef ENABLE_INVOKE_NG
- #include "pygi-invoke-ng.h"
#include "pygi-cache.h"
-#else
- #include "pygi-invoke.h"
#endif
G_BEGIN_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]