summaryrefslogtreecommitdiff
path: root/gi/pygi-cache.c
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:37:07 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:37:09 +0900
commite5d66a3d89168db811dff9a9436f91fe44d74f0f (patch)
tree6f33425764313c4431633c12ee17427b735bcf14 /gi/pygi-cache.c
parent188514abf089f6c3bf73469e83525f3519f15ede (diff)
downloadpygobject2-e5d66a3d89168db811dff9a9436f91fe44d74f0f.tar.gz
pygobject2-e5d66a3d89168db811dff9a9436f91fe44d74f0f.tar.bz2
pygobject2-e5d66a3d89168db811dff9a9436f91fe44d74f0f.zip
Imported Upstream version 2.90.1
Change-Id: I1fc2c61834ea9989bdca62e73c250b1be7c90a37 Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'gi/pygi-cache.c')
-rw-r--r--gi/pygi-cache.c1443
1 files changed, 1443 insertions, 0 deletions
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
new file mode 100644
index 0000000..31dc9e2
--- /dev/null
+++ b/gi/pygi-cache.c
@@ -0,0 +1,1443 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+#include "pygi-info.h"
+#include "pygi-cache.h"
+#include "pygi-marshal-in.h"
+#include "pygi-marshal-out.h"
+#include "pygi-marshal-cleanup.h"
+#include "pygi-type.h"
+#include <girepository.h>
+
+PyGIArgCache * _arg_cache_new (GITypeInfo *type_info,
+ PyGICallableCache *callable_cache,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ GIDirection direction,
+ gssize c_arg_index,
+ gssize py_arg_index);
+
+PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
+ PyGICallableCache *callable_cache,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ GIDirection direction,
+ gssize c_arg_index,
+ gssize py_arg_index);
+/* cleanup */
+void
+_pygi_arg_cache_free (PyGIArgCache *cache)
+{
+ if (cache == NULL)
+ return;
+
+ if (cache->type_info != NULL)
+ g_base_info_unref ( (GIBaseInfo *)cache->type_info);
+ if (cache->destroy_notify)
+ cache->destroy_notify (cache);
+ else
+ g_slice_free (PyGIArgCache, cache);
+}
+
+static void
+_interface_cache_free_func (PyGIInterfaceCache *cache)
+{
+ if (cache != NULL) {
+ Py_XDECREF (cache->py_type);
+ if (cache->type_name != NULL)
+ g_free (cache->type_name);
+ if (cache->interface_info != NULL)
+ g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
+ g_slice_free (PyGIInterfaceCache, cache);
+ }
+}
+
+static void
+_hash_cache_free_func (PyGIHashCache *cache)
+{
+ if (cache != NULL) {
+ _pygi_arg_cache_free (cache->key_cache);
+ _pygi_arg_cache_free (cache->value_cache);
+ g_slice_free (PyGIHashCache, cache);
+ }
+}
+
+static void
+_sequence_cache_free_func (PyGISequenceCache *cache)
+{
+ if (cache != NULL) {
+ _pygi_arg_cache_free (cache->item_cache);
+ g_slice_free (PyGISequenceCache, cache);
+ }
+}
+
+static void
+_callback_cache_free_func (PyGICallbackCache *cache)
+{
+ if (cache != NULL) {
+ if (cache->interface_info != NULL)
+ g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
+
+ g_slice_free (PyGICallbackCache, cache);
+ }
+}
+
+void
+_pygi_callable_cache_free (PyGICallableCache *cache)
+{
+ gssize i;
+
+ if (cache == NULL)
+ return;
+
+ g_slist_free (cache->out_args);
+ g_slist_free (cache->arg_name_list);
+ g_hash_table_destroy (cache->arg_name_hash);
+
+ for (i = 0; i < cache->n_args; i++) {
+ PyGIArgCache *tmp = cache->args_cache[i];
+ _pygi_arg_cache_free (tmp);
+ }
+ if (cache->return_cache != NULL)
+ _pygi_arg_cache_free (cache->return_cache);
+
+ g_slice_free1 (cache->n_args * sizeof (PyGIArgCache *), cache->args_cache);
+ g_slice_free (PyGICallableCache, cache);
+}
+
+/* cache generation */
+
+static PyGIInterfaceCache *
+_interface_cache_new (GIInterfaceInfo *iface_info)
+{
+ PyGIInterfaceCache *ic;
+
+ ic = g_slice_new0 (PyGIInterfaceCache);
+ ( (PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
+ ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
+ ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
+
+ if (ic->py_type == NULL)
+ return NULL;
+
+ ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
+ return ic;
+}
+
+static PyGISequenceCache *
+_sequence_cache_new (GITypeInfo *type_info,
+ GIDirection direction,
+ GITransfer transfer,
+ gssize child_offset)
+{
+ PyGISequenceCache *sc;
+ GITypeInfo *item_type_info;
+ GITypeTag item_type_tag;
+ GITransfer item_transfer;
+
+ sc = g_slice_new0 (PyGISequenceCache);
+ ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
+
+ sc->fixed_size = -1;
+ sc->len_arg_index = -1;
+ sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
+ if (!sc->is_zero_terminated) {
+ sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
+ if (sc->fixed_size < 0)
+ sc->len_arg_index = g_type_info_get_array_length (type_info) + child_offset;
+ }
+
+ item_type_info = g_type_info_get_param_type (type_info, 0);
+
+ item_transfer =
+ transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
+
+ sc->item_cache = _arg_cache_new (item_type_info,
+ NULL,
+ NULL,
+ item_transfer,
+ direction,
+ 0, 0);
+
+ if (sc->item_cache == NULL) {
+ _pygi_arg_cache_free ( (PyGIArgCache *)sc);
+ return NULL;
+ }
+
+ sc->item_size = _pygi_g_type_info_size (item_type_info);
+ g_base_info_unref ( (GIBaseInfo *)item_type_info);
+
+ return sc;
+}
+static PyGIHashCache *
+_hash_cache_new (GITypeInfo *type_info,
+ GIDirection direction,
+ GITransfer transfer)
+{
+ PyGIHashCache *hc;
+ GITypeInfo *key_type_info;
+ GITypeInfo *value_type_info;
+ GITransfer item_transfer;
+
+ hc = g_slice_new0 (PyGIHashCache);
+ ( (PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func;
+ key_type_info = g_type_info_get_param_type (type_info, 0);
+ value_type_info = g_type_info_get_param_type (type_info, 1);
+
+ item_transfer =
+ transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
+
+ hc->key_cache = _arg_cache_new (key_type_info,
+ NULL,
+ NULL,
+ item_transfer,
+ direction,
+ 0, 0);
+
+ if (hc->key_cache == NULL) {
+ _pygi_arg_cache_free ( (PyGIArgCache *)hc);
+ return NULL;
+ }
+
+ hc->value_cache = _arg_cache_new (value_type_info,
+ NULL,
+ NULL,
+ item_transfer,
+ direction,
+ 0, 0);
+
+ if (hc->value_cache == NULL) {
+ _pygi_arg_cache_free ( (PyGIArgCache *)hc);
+ return NULL;
+ }
+
+ g_base_info_unref( (GIBaseInfo *)key_type_info);
+ g_base_info_unref( (GIBaseInfo *)value_type_info);
+
+ return hc;
+}
+
+static PyGICallbackCache *
+_callback_cache_new (GIArgInfo *arg_info,
+ GIInterfaceInfo *iface_info,
+ gssize child_offset)
+{
+ PyGICallbackCache *cc;
+
+ cc = g_slice_new0 (PyGICallbackCache);
+ cc->user_data_index = g_arg_info_get_closure (arg_info);
+ if (cc->user_data_index != -1)
+ cc->user_data_index += child_offset;
+ cc->destroy_notify_index = g_arg_info_get_destroy (arg_info);
+ if (cc->destroy_notify_index != -1)
+ cc->destroy_notify_index += child_offset;
+ cc->scope = g_arg_info_get_scope (arg_info);
+ g_base_info_ref( (GIBaseInfo *)iface_info);
+ cc->interface_info = iface_info;
+ return cc;
+}
+
+static PyGIArgCache *
+_arg_cache_alloc (void)
+{
+ return g_slice_new0 (PyGIArgCache);
+}
+
+static void
+_arg_cache_in_void_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_void;
+}
+
+static void
+_arg_cache_out_void_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_void;
+}
+
+static void
+_arg_cache_in_boolean_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_boolean;
+}
+
+static void
+_arg_cache_out_boolean_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_boolean;
+}
+
+static void
+_arg_cache_in_int8_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_int8;
+}
+
+static void
+_arg_cache_out_int8_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_int8;
+}
+
+static void
+_arg_cache_in_uint8_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_uint8;
+}
+
+static void
+_arg_cache_out_uint8_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_uint8;
+}
+
+static void
+_arg_cache_in_int16_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_int16;
+}
+
+static void
+_arg_cache_out_int16_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_int16;
+}
+
+static void
+_arg_cache_in_uint16_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_uint16;
+}
+
+static void
+_arg_cache_out_uint16_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_uint16;
+}
+
+static void
+_arg_cache_in_int32_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_int32;
+}
+
+static void
+_arg_cache_out_int32_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_int32;
+}
+
+static void
+_arg_cache_in_uint32_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_uint32;
+}
+
+static void
+_arg_cache_out_uint32_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_uint32;
+}
+
+static void
+_arg_cache_in_int64_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_int64;
+}
+
+static void
+_arg_cache_out_int64_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_int64;
+}
+
+static void
+_arg_cache_in_uint64_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_uint64;
+}
+
+static void
+_arg_cache_out_uint64_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_uint64;
+}
+
+static void
+_arg_cache_in_float_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_float;
+}
+
+static void
+_arg_cache_out_float_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_float;
+}
+
+static void
+_arg_cache_in_double_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_double;
+}
+
+static void
+_arg_cache_out_double_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_double;
+}
+
+static void
+_arg_cache_in_unichar_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_unichar;
+}
+
+static void
+_arg_cache_out_unichar_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_unichar;
+}
+
+static void
+_arg_cache_in_gtype_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_gtype;
+}
+
+static void
+_arg_cache_out_gtype_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_gtype;
+}
+
+static void
+_arg_cache_in_utf8_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_utf8;
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_in_utf8;
+}
+
+static void
+_arg_cache_out_utf8_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_utf8;
+ arg_cache->out_cleanup = _pygi_marshal_cleanup_out_utf8;
+}
+
+static void
+_arg_cache_in_filename_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_filename;
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_in_utf8;
+}
+
+static void
+_arg_cache_out_filename_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_filename;
+ arg_cache->out_cleanup = _pygi_marshal_cleanup_out_utf8;
+}
+
+static gboolean
+_arg_cache_in_array_setup (PyGIArgCache *arg_cache,
+ PyGICallableCache *callable_cache,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ GIDirection direction)
+{
+ PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ seq_cache->array_type = g_type_info_get_array_type (type_info);
+
+ arg_cache->in_marshaller = _pygi_marshal_in_array;
+
+ if (seq_cache->len_arg_index >= 0 &&
+ direction == GI_DIRECTION_IN) {
+ PyGIArgCache *child_cache =
+ callable_cache->args_cache[seq_cache->len_arg_index];
+
+ if (child_cache == NULL) {
+ child_cache = _arg_cache_alloc ();
+ } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD) {
+ return TRUE;
+ }
+
+ child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+ child_cache->direction = direction;
+ child_cache->in_marshaller = NULL;
+ child_cache->out_marshaller = NULL;
+
+ callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
+ }
+
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_in_array;
+
+ return TRUE;
+}
+
+static gboolean
+_arg_cache_out_array_setup (PyGIArgCache *arg_cache,
+ PyGICallableCache *callable_cache,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ GIDirection direction,
+ gssize arg_index)
+{
+ PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ arg_cache->out_marshaller = _pygi_marshal_out_array;
+ arg_cache->out_cleanup = _pygi_marshal_cleanup_out_array;
+
+ seq_cache->array_type = g_type_info_get_array_type (type_info);
+
+ if (seq_cache->len_arg_index >= 0) {
+ PyGIArgCache *child_cache = callable_cache->args_cache[seq_cache->len_arg_index];
+ if (seq_cache->len_arg_index < arg_index)
+ callable_cache->n_out_child_args++;
+
+ if (child_cache != NULL) {
+ if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
+ return TRUE;
+
+ callable_cache->out_args =
+ g_slist_remove (callable_cache->out_args, child_cache);
+ } else {
+ child_cache = _arg_cache_alloc ();
+ }
+
+ child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+ child_cache->direction = direction;
+ child_cache->in_marshaller = NULL;
+ child_cache->out_marshaller = NULL;
+
+ callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
+ }
+
+ return TRUE;
+}
+
+static void
+_arg_cache_in_glist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_glist;
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_in_glist;
+}
+
+static void
+_arg_cache_out_glist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_glist;
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_out_glist;
+}
+
+static void
+_arg_cache_in_gslist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_gslist;
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_in_glist;
+}
+
+static void
+_arg_cache_out_gslist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_gslist;
+ arg_cache->out_cleanup = _pygi_marshal_cleanup_out_glist;
+}
+
+static void
+_arg_cache_in_ghash_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_ghash;
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_in_ghash;
+}
+
+static void
+_arg_cache_out_ghash_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_ghash;
+ arg_cache->out_cleanup = _pygi_marshal_cleanup_out_ghash;
+}
+
+static void
+_arg_cache_in_gerror_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_gerror;
+ arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+}
+
+static void
+_arg_cache_out_gerror_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_gerror;
+ arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+}
+
+static void
+_arg_cache_in_interface_union_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
+}
+
+static void
+_arg_cache_out_interface_union_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
+}
+
+static void
+_arg_cache_in_interface_struct_setup (PyGIArgCache *arg_cache,
+ GIInterfaceInfo *iface_info,
+ GITransfer transfer)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
+ arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
+
+ if (iface_cache->g_type == G_TYPE_VALUE)
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_in_interface_struct_gvalue;
+ else if (iface_cache->is_foreign)
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_in_interface_struct_foreign;
+}
+
+static void
+_arg_cache_out_interface_struct_setup (PyGIArgCache *arg_cache,
+ GIInterfaceInfo *iface_info,
+ GITransfer transfer)
+{
+ PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+ iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
+ arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
+
+ if (iface_cache->is_foreign)
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_out_interface_struct_foreign;
+}
+
+static void
+_arg_cache_in_interface_object_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_interface_object;
+ arg_cache->in_cleanup = _pygi_marshal_cleanup_in_interface_object;
+}
+
+static void
+_arg_cache_out_interface_object_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_interface_object;
+ arg_cache->out_cleanup = _pygi_marshal_cleanup_out_interface_object;
+}
+
+static void
+_arg_cache_in_interface_callback_setup (PyGIArgCache *arg_cache,
+ PyGICallableCache *callable_cache)
+{
+ PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
+ if (callback_cache->user_data_index >= 0) {
+ PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
+ user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
+ callable_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
+ }
+
+ if (callback_cache->destroy_notify_index >= 0) {
+ PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
+ destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+ callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
+ }
+ arg_cache->in_marshaller = _pygi_marshal_in_interface_callback;
+}
+
+static void
+_arg_cache_out_interface_callback_setup (void)
+{
+ PyErr_Format(PyExc_NotImplementedError,
+ "Callback returns are not supported");
+}
+
+static void
+_arg_cache_in_interface_enum_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_interface_enum;
+}
+
+static void
+_arg_cache_out_interface_enum_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_interface_enum;
+}
+
+static void
+_arg_cache_in_interface_flags_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->in_marshaller = _pygi_marshal_in_interface_flags;
+}
+
+static void
+_arg_cache_out_interface_flags_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->out_marshaller = _pygi_marshal_out_interface_flags;
+}
+
+PyGIArgCache *
+_arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
+ PyGICallableCache *callable_cache,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ GIDirection direction,
+ gssize c_arg_index,
+ gssize py_arg_index)
+{
+ PyGIInterfaceCache *iface_cache = NULL;
+ PyGIArgCache *arg_cache = NULL;
+ gssize child_offset = 0;
+ GIInfoType info_type;
+
+ if (callable_cache != NULL)
+ child_offset =
+ (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
+ callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
+
+ GI_IS_INTERFACE_INFO (iface_info);
+
+ info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);
+
+ /* Callbacks are special cased */
+ if (info_type != GI_INFO_TYPE_CALLBACK) {
+ iface_cache = _interface_cache_new (iface_info);
+
+ arg_cache = (PyGIArgCache *)iface_cache;
+ if (arg_cache == NULL)
+ return NULL;
+ }
+
+ switch (info_type) {
+ case GI_INFO_TYPE_UNION:
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_interface_union_setup (arg_cache, transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_interface_union_setup (arg_cache, transfer);
+
+ break;
+ case GI_INFO_TYPE_STRUCT:
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+
+ break;
+ case GI_INFO_TYPE_OBJECT:
+ case GI_INFO_TYPE_INTERFACE:
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_interface_object_setup (arg_cache, transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_interface_object_setup (arg_cache, transfer);
+
+ break;
+ case GI_INFO_TYPE_BOXED:
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+
+ break;
+ case GI_INFO_TYPE_CALLBACK:
+ {
+ PyGICallbackCache *callback_cache;
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
+ _arg_cache_out_interface_callback_setup ();
+ return NULL;
+ }
+
+ callback_cache =
+ _callback_cache_new (arg_info,
+ iface_info,
+ child_offset);
+
+ arg_cache = (PyGIArgCache *)callback_cache;
+ if (arg_cache == NULL)
+ return NULL;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_interface_callback_setup (arg_cache, callable_cache);
+
+ break;
+ }
+ case GI_INFO_TYPE_ENUM:
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_interface_enum_setup (arg_cache, transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_interface_enum_setup (arg_cache, transfer);
+
+ break;
+ case GI_INFO_TYPE_FLAGS:
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_interface_flags_setup (arg_cache, transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_interface_flags_setup (arg_cache, transfer);
+
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (arg_cache != NULL) {
+ arg_cache->direction = direction;
+ arg_cache->transfer = transfer;
+ arg_cache->type_tag = GI_TYPE_TAG_INTERFACE;
+ arg_cache->py_arg_index = py_arg_index;
+ arg_cache->c_arg_index = c_arg_index;
+
+ if (iface_cache != NULL) {
+ g_base_info_ref ( (GIBaseInfo *)iface_info);
+ iface_cache->interface_info = iface_info;
+ }
+ }
+
+ return arg_cache;
+}
+
+PyGIArgCache *
+_arg_cache_new (GITypeInfo *type_info,
+ PyGICallableCache *callable_cache,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ GIDirection direction,
+ gssize c_arg_index,
+ gssize py_arg_index)
+{
+ PyGIArgCache *arg_cache = NULL;
+ gssize child_offset = 0;
+ GITypeTag type_tag;
+
+ GI_IS_TYPE_INFO (type_info);
+
+ type_tag = g_type_info_get_tag (type_info);
+
+ if (callable_cache != NULL)
+ child_offset =
+ (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
+ callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
+
+ switch (type_tag) {
+ case GI_TYPE_TAG_VOID:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_void_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_void_setup (arg_cache);
+ break;
+ case GI_TYPE_TAG_BOOLEAN:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_boolean_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_boolean_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_INT8:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_int8_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_int8_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_UINT8:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_uint8_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_uint8_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_INT16:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_int16_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_int16_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_UINT16:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_uint16_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_uint16_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_INT32:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_int32_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_int32_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_UINT32:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_uint32_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_uint32_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_INT64:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_int64_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_int64_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_UINT64:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_uint64_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_uint64_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_float_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_float_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_double_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_double_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_UNICHAR:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_unichar_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_unichar_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_GTYPE:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_gtype_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_gtype_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_UTF8:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_utf8_setup (arg_cache, transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_utf8_setup (arg_cache, transfer);
+
+ break;
+ case GI_TYPE_TAG_FILENAME:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_filename_setup (arg_cache, transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_filename_setup (arg_cache, transfer);
+
+ break;
+ case GI_TYPE_TAG_ARRAY:
+ {
+ PyGISequenceCache *seq_cache =
+ _sequence_cache_new (type_info,
+ direction,
+ transfer,
+ child_offset);
+
+ arg_cache = (PyGIArgCache *)seq_cache;
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_array_setup (arg_cache,
+ callable_cache,
+ type_info,
+ transfer,
+ direction);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_array_setup (arg_cache,
+ callable_cache,
+ type_info,
+ transfer,
+ direction,
+ c_arg_index);
+
+ /* ugly edge case code:
+ *
+ * length can come before the array parameter which means we
+ * need to update indexes if this happens
+ */
+ if (seq_cache->len_arg_index > -1 &&
+ seq_cache->len_arg_index < c_arg_index) {
+ gssize i;
+
+ py_arg_index -= 1;
+ callable_cache->n_py_args -= 1;
+
+ for (i = seq_cache->len_arg_index + 1;
+ i < callable_cache->n_args;
+ i++) {
+ PyGIArgCache *update_cache = callable_cache->args_cache[i];
+ if (update_cache == NULL)
+ break;
+
+ update_cache->py_arg_index -= 1;
+ }
+ }
+
+ break;
+ }
+ case GI_TYPE_TAG_GLIST:
+ {
+ PyGISequenceCache *seq_cache =
+ _sequence_cache_new (type_info,
+ direction,
+ transfer,
+ child_offset);
+
+ arg_cache = (PyGIArgCache *)seq_cache;
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_glist_setup (arg_cache, transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_glist_setup (arg_cache, transfer);
+
+
+ break;
+ }
+ case GI_TYPE_TAG_GSLIST:
+ {
+ PyGISequenceCache *seq_cache =
+ _sequence_cache_new (type_info,
+ direction,
+ transfer,
+ child_offset);
+
+ arg_cache = (PyGIArgCache *)seq_cache;
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_gslist_setup (arg_cache, transfer);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_gslist_setup (arg_cache, transfer);
+
+ break;
+ }
+ case GI_TYPE_TAG_GHASH:
+ arg_cache =
+ (PyGIArgCache *)_hash_cache_new (type_info,
+ direction,
+ transfer);
+
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_ghash_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
+ _arg_cache_out_ghash_setup (arg_cache);
+ }
+
+ break;
+ case GI_TYPE_TAG_INTERFACE:
+ {
+ GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
+ arg_cache = _arg_cache_new_for_interface (interface_info,
+ callable_cache,
+ arg_info,
+ transfer,
+ direction,
+ c_arg_index,
+ py_arg_index);
+
+ g_base_info_unref ( (GIBaseInfo *)interface_info);
+ break;
+ }
+ case GI_TYPE_TAG_ERROR:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+ _arg_cache_in_gerror_setup (arg_cache);
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+ _arg_cache_out_gerror_setup (arg_cache);
+
+ break;
+ }
+
+ if (arg_cache != NULL) {
+ arg_cache->direction = direction;
+ arg_cache->transfer = transfer;
+ arg_cache->type_tag = type_tag;
+ arg_cache->py_arg_index = py_arg_index;
+ arg_cache->c_arg_index = c_arg_index;
+ arg_cache->is_pointer = g_type_info_is_pointer (type_info);
+ g_base_info_ref ( (GIBaseInfo *) type_info);
+ arg_cache->type_info = type_info;
+ }
+
+ return arg_cache;
+}
+
+static void
+_arg_name_list_generate (PyGICallableCache *callable_cache)
+{
+ GSList * arg_name_list = NULL;
+
+ if (callable_cache->arg_name_hash == NULL) {
+ callable_cache->arg_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ } else {
+ g_hash_table_remove_all (callable_cache->arg_name_hash);
+ }
+
+ for (int i=0; i < callable_cache->n_args; i++) {
+ PyGIArgCache *arg_cache = NULL;
+
+ arg_cache = callable_cache->args_cache[i];
+
+ if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD &&
+ (arg_cache->direction == GI_DIRECTION_IN ||
+ arg_cache->direction == GI_DIRECTION_INOUT)) {
+
+ gpointer arg_name = (gpointer)arg_cache->arg_name;
+
+ arg_name_list = g_slist_prepend (arg_name_list, arg_name);
+ if (arg_name != NULL) {
+ g_hash_table_insert (callable_cache->arg_name_hash, arg_name, arg_name);
+ }
+ }
+ }
+
+ callable_cache->arg_name_list = g_slist_reverse (arg_name_list);
+}
+
+/* Generate the cache for the callable's arguments */
+static gboolean
+_args_cache_generate (GICallableInfo *callable_info,
+ PyGICallableCache *callable_cache)
+{
+ gssize arg_index = 0;
+ gssize i;
+ GITypeInfo *return_info;
+ GITransfer return_transfer;
+ PyGIArgCache *return_cache;
+
+ /* cache the return arg */
+ return_info =
+ g_callable_info_get_return_type (callable_info);
+ return_transfer =
+ g_callable_info_get_caller_owns (callable_info);
+ return_cache =
+ _arg_cache_new (return_info,
+ callable_cache,
+ NULL,
+ return_transfer,
+ GI_DIRECTION_OUT,
+ -1,
+ -1);
+
+ callable_cache->return_cache = return_cache;
+ g_base_info_unref (return_info);
+
+ /* first arg is the instance */
+ if (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
+ callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
+ GIInterfaceInfo *interface_info;
+ PyGIArgCache *instance_cache;
+
+ interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
+
+ instance_cache =
+ _arg_cache_new_for_interface (interface_info,
+ callable_cache,
+ NULL,
+ GI_TRANSFER_NOTHING,
+ GI_DIRECTION_IN,
+ arg_index,
+ 0);
+
+ instance_cache->in_marshaller = _pygi_marshal_in_interface_instance;
+ g_base_info_unref ( (GIBaseInfo *)interface_info);
+
+ if (instance_cache == NULL)
+ return FALSE;
+
+ callable_cache->args_cache[arg_index] = instance_cache;
+
+ arg_index++;
+ callable_cache->n_in_args++;
+ callable_cache->n_py_args++;
+ }
+
+
+ for (i=0; arg_index < callable_cache->n_args; arg_index++, i++) {
+ PyGIArgCache *arg_cache = NULL;
+ GIArgInfo *arg_info;
+ GITypeInfo *type_info;
+ GIDirection direction;
+ GITransfer transfer;
+ GITypeTag type_tag;
+ gboolean is_caller_allocates = FALSE;
+ gssize py_arg_index = -1;
+
+ arg_info =
+ g_callable_info_get_arg (callable_info, i);
+
+ direction = g_arg_info_get_direction (arg_info);
+ transfer = g_arg_info_get_ownership_transfer (arg_info);
+ type_info = g_arg_info_get_type (arg_info);
+ type_tag = g_type_info_get_tag (type_info);
+
+ if (type_tag == GI_TYPE_TAG_INTERFACE)
+ is_caller_allocates = g_arg_info_is_caller_allocates (arg_info);
+
+ /* must be an child arg filled in by its owner
+ * fill in it's c_arg_index, add to the in count
+ * and continue
+ */
+ if (callable_cache->args_cache[arg_index] != NULL) {
+ arg_cache = callable_cache->args_cache[arg_index];
+ if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) {
+ arg_cache->py_arg_index = callable_cache->n_py_args;
+ callable_cache->n_py_args++;
+ }
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
+ arg_cache->c_arg_index = callable_cache->n_in_args;
+ callable_cache->n_in_args++;
+ }
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
+ callable_cache->n_out_args++;
+ callable_cache->n_out_child_args++;
+ }
+
+ g_base_info_unref ( (GIBaseInfo *)arg_info);
+ continue;
+ }
+
+ if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
+ py_arg_index = callable_cache->n_py_args;
+ callable_cache->n_in_args++;
+ callable_cache->n_py_args++;
+ }
+
+ arg_cache =
+ _arg_cache_new (type_info,
+ callable_cache,
+ arg_info,
+ transfer,
+ direction,
+ arg_index,
+ py_arg_index);
+
+ if (arg_cache == NULL)
+ goto arg_err;
+
+ arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
+ arg_cache->allow_none = g_arg_info_may_be_null(arg_info);
+ arg_cache->is_caller_allocates = is_caller_allocates;
+
+ if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
+ callable_cache->n_out_args++;
+
+ if (arg_cache == NULL)
+ goto arg_err;
+
+ callable_cache->out_args =
+ g_slist_append (callable_cache->out_args, arg_cache);
+ }
+
+ callable_cache->args_cache[arg_index] = arg_cache;
+ g_base_info_unref( (GIBaseInfo *)type_info);
+ g_base_info_unref( (GIBaseInfo *)arg_info);
+
+ continue;
+arg_err:
+ g_base_info_unref( (GIBaseInfo *)type_info);
+ g_base_info_unref( (GIBaseInfo *)arg_info);
+ return FALSE;
+ }
+
+ _arg_name_list_generate (callable_cache);
+
+ return TRUE;
+}
+
+PyGICallableCache *
+_pygi_callable_cache_new (GICallableInfo *callable_info)
+{
+ PyGICallableCache *cache;
+ GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
+
+ cache = g_slice_new0 (PyGICallableCache);
+
+ if (cache == NULL)
+ return NULL;
+
+ cache->name = g_base_info_get_name ((GIBaseInfo *)callable_info);
+
+ if (type == GI_INFO_TYPE_FUNCTION) {
+ GIFunctionInfoFlags flags;
+
+ flags = g_function_info_get_flags ( (GIFunctionInfo *)callable_info);
+
+ if (flags & GI_FUNCTION_IS_CONSTRUCTOR)
+ cache->function_type = PYGI_FUNCTION_TYPE_CONSTRUCTOR;
+ else if (flags & GI_FUNCTION_IS_METHOD)
+ cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
+ } else if (type == GI_INFO_TYPE_VFUNC) {
+ cache->function_type = PYGI_FUNCTION_TYPE_VFUNC;
+ } else if (type == GI_INFO_TYPE_CALLBACK) {
+ cache->function_type = PYGI_FUNCTION_TYPE_CALLBACK;
+ } else {
+ cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
+ }
+
+ cache->n_args = g_callable_info_get_n_args (callable_info);
+
+ /* if we are a method or vfunc make sure the instance parameter is counted */
+ if (cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
+ cache->function_type == PYGI_FUNCTION_TYPE_VFUNC)
+ cache->n_args++;
+
+ if (cache->n_args > 0)
+ cache->args_cache = g_slice_alloc0 (cache->n_args * sizeof (PyGIArgCache *));
+
+ if (!_args_cache_generate (callable_info, cache))
+ goto err;
+
+ return cache;
+err:
+ _pygi_callable_cache_free (cache);
+ return NULL;
+}