summaryrefslogtreecommitdiff
path: root/gi/pygi-cache.c
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:46:30 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:46:33 +0900
commitdca4e6423c560689ee831785473ad3ab48e7548a (patch)
tree048ddb6edb0826be8ff180c027d45acb6dac67db /gi/pygi-cache.c
parent392945d666d2cfb31a844826a72b1eb65a52546f (diff)
downloadpygobject2-dca4e6423c560689ee831785473ad3ab48e7548a.tar.gz
pygobject2-dca4e6423c560689ee831785473ad3ab48e7548a.tar.bz2
pygobject2-dca4e6423c560689ee831785473ad3ab48e7548a.zip
Imported Upstream version 3.3.1
Change-Id: I7e59d7cf82217b545ec40115122a83ebf79763cb Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'gi/pygi-cache.c')
-rw-r--r--gi/pygi-cache.c2120
1 files changed, 1218 insertions, 902 deletions
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 82a6182..610e35b 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -2,7 +2,6 @@
* vim: tabstop=4 shiftwidth=4 expandtab
*
* Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
- * Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,100 +14,37 @@
* 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, see <http://www.gnu.org/licenses/>.
+ * 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 <Python.h>
-#include <girepository.h>
-
-#include "pyglib.h"
-#include "pygtype.h"
#include "pygi-info.h"
#include "pygi-cache.h"
+#include "pygi-marshal-to-py.h"
+#include "pygi-marshal-from-py.h"
#include "pygi-marshal-cleanup.h"
#include "pygi-type.h"
-#include "pygi-hashtable.h"
-#include "pygi-basictype.h"
-#include "pygi-list.h"
-#include "pygi-array.h"
-#include "pygi-closure.h"
-#include "pygi-error.h"
-#include "pygi-object.h"
-#include "pygi-struct-marshal.h"
-#include "pygi-enum-marshal.h"
-#include "pygi-resulttuple.h"
-#include "pygi-invoke.h"
-
-
-/* _arg_info_default_value
- * info:
- * arg: (out): GIArgument to fill in with default value.
- *
- * This is currently a place holder API which only supports "allow-none" pointer args.
- * Once defaults are part of the GI API, we can replace this with: g_arg_info_default_value
- * https://bugzilla.gnome.org/show_bug.cgi?id=558620
- *
- * Returns: TRUE if the given argument supports a default value and was filled in.
- */
-static gboolean
-_arg_info_default_value (GIArgInfo *info, GIArgument *arg)
-{
- if (g_arg_info_may_be_null (info)) {
- arg->v_pointer = NULL;
- return TRUE;
- }
- return FALSE;
-}
-
-/* pygi_arg_base_setup:
- * arg_cache: argument cache to initialize
- * type_info: source for type related attributes to cache
- * arg_info: (allow-none): source for argument related attributes to cache
- * transfer: transfer mode to store in the argument cache
- * direction: marshaling direction to store in the cache
- *
- * Initializer for PyGIArgCache
- *
- * Returns: TRUE on success and FALSE on failure
- */
-gboolean
-pygi_arg_base_setup (PyGIArgCache *arg_cache,
- GITypeInfo *type_info,
- GIArgInfo *arg_info, /* may be NULL for return arguments */
- GITransfer transfer,
- PyGIDirection direction)
-{
- arg_cache->direction = direction;
- arg_cache->transfer = transfer;
- arg_cache->py_arg_index = -1;
- arg_cache->c_arg_index = -1;
-
- if (type_info != NULL) {
- arg_cache->is_pointer = g_type_info_is_pointer (type_info);
- arg_cache->type_tag = g_type_info_get_tag (type_info);
- g_base_info_ref ( (GIBaseInfo *) type_info);
- arg_cache->type_info = type_info;
- }
-
- if (arg_info != NULL) {
- if (!arg_cache->has_default) {
- /* It is possible has_default was set somewhere else */
- arg_cache->has_default = _arg_info_default_value (arg_info,
- &arg_cache->default_value);
- }
- arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
- arg_cache->allow_none = g_arg_info_may_be_null (arg_info);
-
- if (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE || arg_cache->type_tag == GI_TYPE_TAG_ARRAY)
- arg_cache->is_caller_allocates = g_arg_info_is_caller_allocates (arg_info);
- else
- arg_cache->is_caller_allocates = FALSE;
- }
- return TRUE;
-}
+#include <girepository.h>
+PyGIArgCache * _arg_cache_new (GITypeInfo *type_info,
+ PyGICallableCache *callable_cache,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection 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,
+ PyGIDirection direction,
+ gssize c_arg_index,
+ gssize py_arg_index);
+/* cleanup */
void
-pygi_arg_cache_free (PyGIArgCache *cache)
+_pygi_arg_cache_free (PyGIArgCache *cache)
{
if (cache == NULL)
return;
@@ -121,8 +57,6 @@ pygi_arg_cache_free (PyGIArgCache *cache)
g_slice_free (PyGIArgCache, cache);
}
-/* PyGIInterfaceCache */
-
static void
_interface_cache_free_func (PyGIInterfaceCache *cache)
{
@@ -136,1050 +70,1432 @@ _interface_cache_free_func (PyGIInterfaceCache *cache)
}
}
-/* pygi_arg_interface_setup:
- * arg_cache: argument cache to initialize
- * type_info: source for type related attributes to cache
- * arg_info: (allow-none): source for argument related attributes to cache
- * transfer: transfer mode to store in the argument cache
- * direction: marshaling direction to store in the cache
- * iface_info: interface info to cache
- *
- * Initializer for PyGIInterfaceCache
- *
- * Returns: TRUE on success and FALSE on failure
- */
-gboolean
-pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache,
- GITypeInfo *type_info,
- GIArgInfo *arg_info, /* may be NULL for return arguments */
- GITransfer transfer,
- PyGIDirection direction,
- GIInterfaceInfo *iface_info)
-{
- if (!pygi_arg_base_setup ((PyGIArgCache *)iface_cache,
- type_info,
- arg_info,
- transfer,
- direction)) {
- return FALSE;
+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);
}
+}
- ( (PyGIArgCache *)iface_cache)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
+static void
+_sequence_cache_free_func (PyGISequenceCache *cache)
+{
+ if (cache != NULL) {
+ _pygi_arg_cache_free (cache->item_cache);
+ g_slice_free (PyGISequenceCache, cache);
+ }
+}
- g_base_info_ref ( (GIBaseInfo *)iface_info);
- iface_cache->interface_info = iface_info;
- iface_cache->arg_cache.type_tag = GI_TYPE_TAG_INTERFACE;
- iface_cache->type_name = _pygi_g_base_info_get_fullname (iface_info);
- iface_cache->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
- iface_cache->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
+static void
+_callback_cache_free_func (PyGICallbackCache *cache)
+{
+ if (cache != NULL) {
+ if (cache->interface_info != NULL)
+ g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
- if (iface_cache->py_type == NULL) {
- return FALSE;
+ g_slice_free (PyGICallbackCache, cache);
}
-
- return TRUE;
}
-PyGIArgCache *
-pygi_arg_interface_new_from_info (GITypeInfo *type_info,
- GIArgInfo *arg_info, /* may be NULL for return arguments */
- GITransfer transfer,
- PyGIDirection direction,
- GIInterfaceInfo *iface_info)
+void
+_pygi_callable_cache_free (PyGICallableCache *cache)
{
- PyGIInterfaceCache *ic;
+ gssize i;
- ic = g_slice_new0 (PyGIInterfaceCache);
- if (!pygi_arg_interface_setup (ic,
- type_info,
- arg_info,
- transfer,
- direction,
- iface_info)) {
- pygi_arg_cache_free ((PyGIArgCache *)ic);
- return NULL;
+ if (cache == NULL)
+ return;
+
+ g_slist_free (cache->to_py_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);
- return (PyGIArgCache *)ic;
+ g_slice_free1 (cache->n_args * sizeof (PyGIArgCache *), cache->args_cache);
+ g_slice_free (PyGICallableCache, cache);
}
-/* PyGISequenceCache */
+/* cache generation */
-static void
-_sequence_cache_free_func (PyGISequenceCache *cache)
+static PyGIInterfaceCache *
+_interface_cache_new (GIInterfaceInfo *iface_info)
{
- if (cache != NULL) {
- pygi_arg_cache_free (cache->item_cache);
- g_slice_free (PyGISequenceCache, cache);
- }
+ 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;
}
-/* pygi_arg_sequence_setup:
- * sc: sequence cache to initialize
- * type_info: source for type related attributes to cache
- * arg_info: (allow-none): source for argument related attributes to cache
- * transfer: transfer mode to store in the argument cache
- * direction: marshaling direction to store in the cache
- * iface_info: interface info to cache
- *
- * Initializer for PyGISequenceCache used for holding list and array argument
- * caches.
- *
- * Returns: TRUE on success and FALSE on failure
- */
-gboolean
-pygi_arg_sequence_setup (PyGISequenceCache *sc,
- GITypeInfo *type_info,
- GIArgInfo *arg_info, /* may be NULL for return arguments */
- GITransfer transfer,
- PyGIDirection direction,
- PyGICallableCache *callable_cache)
+static PyGISequenceCache *
+_sequence_cache_new (GITypeInfo *type_info,
+ GIDirection direction,
+ GITransfer transfer,
+ gssize child_offset)
{
+ PyGISequenceCache *sc;
GITypeInfo *item_type_info;
GITransfer item_transfer;
- if (!pygi_arg_base_setup ((PyGIArgCache *)sc,
- type_info,
- arg_info,
- transfer,
- direction)) {
- return FALSE;
+ 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);
+ if (sc->len_arg_index >= 0)
+ sc->len_arg_index += child_offset;
}
- sc->arg_cache.destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
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 = pygi_arg_cache_new (item_type_info,
- NULL,
- item_transfer,
- direction,
- callable_cache,
- 0, 0);
+ 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);
- if (sc->item_cache == NULL) {
- return FALSE;
+ 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;
}
- return TRUE;
+ 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;
}
-PyGIArgCache *
-pygi_arg_cache_alloc (void)
+static PyGICallbackCache *
+_callback_cache_new (GIArgInfo *arg_info,
+ GIInterfaceInfo *iface_info,
+ gssize child_offset)
{
- return g_slice_new0 (PyGIArgCache);
+ PyGICallbackCache *cc;
+
+ cc = g_slice_new0 (PyGICallbackCache);
+ ( (PyGIArgCache *)cc)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;
+
+ 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_new_for_interface (GIInterfaceInfo *iface_info,
- GITypeInfo *type_info,
- GIArgInfo *arg_info,
- GITransfer transfer,
- PyGIDirection direction,
- PyGICallableCache *callable_cache)
+_arg_cache_alloc (void)
{
- GIInfoType info_type;
-
- info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);
-
- switch (info_type) {
- case GI_INFO_TYPE_CALLBACK:
- return pygi_arg_callback_new_from_info (type_info,
- arg_info,
- transfer,
- direction,
- iface_info,
- callable_cache);
- case GI_INFO_TYPE_OBJECT:
- case GI_INFO_TYPE_INTERFACE:
- return pygi_arg_gobject_new_from_info (type_info,
- arg_info,
- transfer,
- direction,
- iface_info,
- callable_cache);
- case GI_INFO_TYPE_BOXED:
- case GI_INFO_TYPE_STRUCT:
- case GI_INFO_TYPE_UNION:
- return pygi_arg_struct_new_from_info (type_info,
- arg_info,
- transfer,
- direction,
- iface_info);
- case GI_INFO_TYPE_ENUM:
- return pygi_arg_enum_new_from_info (type_info,
- arg_info,
- transfer,
- direction,
- iface_info);
- case GI_INFO_TYPE_FLAGS:
- return pygi_arg_flags_new_from_info (type_info,
- arg_info,
- transfer,
- direction,
- iface_info);
- default:
- g_assert_not_reached ();
- }
-
- return NULL;
+ return g_slice_new0 (PyGIArgCache);
}
-PyGIArgCache *
-pygi_arg_cache_new (GITypeInfo *type_info,
- GIArgInfo *arg_info, /* may be null */
- GITransfer transfer,
- PyGIDirection direction,
- PyGICallableCache *callable_cache,
- gssize c_arg_index,
- gssize py_arg_index)
+static void
+_arg_cache_from_py_void_setup (PyGIArgCache *arg_cache)
{
- PyGIArgCache *arg_cache = NULL;
- GITypeTag type_tag;
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_void;
+}
- type_tag = g_type_info_get_tag (type_info);
+static void
+_arg_cache_to_py_void_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_void;
+}
- switch (type_tag) {
- case GI_TYPE_TAG_VOID:
- 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_UNICHAR:
- case GI_TYPE_TAG_GTYPE:
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- arg_cache = pygi_arg_basic_type_new_from_info (type_info,
- arg_info,
- transfer,
- direction);
- break;
+static void
+_arg_cache_from_py_boolean_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_boolean;
+}
- case GI_TYPE_TAG_ARRAY:
- {
- arg_cache = pygi_arg_garray_new_from_info (type_info,
- arg_info,
- transfer,
- direction,
- callable_cache);
- if (arg_cache == NULL)
- return NULL;
-
- pygi_arg_garray_len_arg_setup (arg_cache,
- type_info,
- callable_cache,
- direction,
- c_arg_index,
- &py_arg_index);
- }
- break;
+static void
+_arg_cache_to_py_boolean_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_boolean;
+}
- case GI_TYPE_TAG_GLIST:
- arg_cache = pygi_arg_glist_new_from_info (type_info,
- arg_info,
- transfer,
- direction,
- callable_cache);
- break;
+static void
+_arg_cache_from_py_int8_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_int8;
+}
- case GI_TYPE_TAG_GSLIST:
- arg_cache = pygi_arg_gslist_new_from_info (type_info,
- arg_info,
- transfer,
- direction,
- callable_cache);
- break;
+static void
+_arg_cache_to_py_int8_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_int8;
+}
- case GI_TYPE_TAG_GHASH:
- arg_cache = pygi_arg_hash_table_new_from_info (type_info,
- arg_info,
- transfer,
- direction,
- callable_cache);
- break;
+static void
+_arg_cache_from_py_uint8_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_uint8;
+}
- case GI_TYPE_TAG_INTERFACE:
- {
- GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info);
- arg_cache = _arg_cache_new_for_interface (interface_info,
- type_info,
- arg_info,
- transfer,
- direction,
- callable_cache);
+static void
+_arg_cache_to_py_uint8_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_uint8;
+}
- g_base_info_unref ( (GIBaseInfo *)interface_info);
- }
- break;
+static void
+_arg_cache_from_py_int16_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_int16;
+}
- case GI_TYPE_TAG_ERROR:
- arg_cache = pygi_arg_gerror_new_from_info (type_info,
- arg_info,
- transfer,
- direction);
- break;
- default:
- break;
- }
+static void
+_arg_cache_to_py_int16_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_int16;
+}
- if (arg_cache != NULL) {
- arg_cache->py_arg_index = py_arg_index;
- arg_cache->c_arg_index = c_arg_index;
- }
+static void
+_arg_cache_from_py_uint16_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_uint16;
+}
- return arg_cache;
+static void
+_arg_cache_to_py_uint16_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_uint16;
}
-/* PyGICallableCache */
+static void
+_arg_cache_from_py_int32_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_int32;
+}
-static PyGIDirection
-_pygi_get_direction (PyGICallableCache *callable_cache, GIDirection gi_direction)
+static void
+_arg_cache_to_py_int32_setup (PyGIArgCache *arg_cache)
{
- /* For vfuncs and callbacks our marshalling directions are reversed */
- if (gi_direction == GI_DIRECTION_INOUT) {
- return PYGI_DIRECTION_BIDIRECTIONAL;
- } else if (gi_direction == GI_DIRECTION_IN) {
- if (callable_cache->calling_context != PYGI_CALLING_CONTEXT_IS_FROM_PY)
- return PYGI_DIRECTION_TO_PYTHON;
- return PYGI_DIRECTION_FROM_PYTHON;
- } else {
- if (callable_cache->calling_context != PYGI_CALLING_CONTEXT_IS_FROM_PY)
- return PYGI_DIRECTION_FROM_PYTHON;
- return PYGI_DIRECTION_TO_PYTHON;
- }
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_int32;
}
-/* Generate the cache for the callable's arguments */
-static gboolean
-_callable_cache_generate_args_cache_real (PyGICallableCache *callable_cache,
- GICallableInfo *callable_info)
+static void
+_arg_cache_from_py_uint32_setup (PyGIArgCache *arg_cache)
{
- gssize i;
- gssize arg_index;
- GITypeInfo *return_info;
- GITransfer return_transfer;
- PyGIArgCache *return_cache;
- PyGIDirection return_direction;
- gssize last_explicit_arg_index;
- PyObject *tuple_names;
- GSList *arg_cache_item;
- PyTypeObject* resulttuple_type;
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_uint32;
+}
- /* Return arguments are always considered out */
- return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT);
+static void
+_arg_cache_to_py_uint32_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_uint32;
+}
- /* 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 =
- pygi_arg_cache_new (return_info,
- NULL,
- return_transfer,
- return_direction,
- callable_cache,
- -1,
- -1);
- if (return_cache == NULL)
- return FALSE;
+static void
+_arg_cache_from_py_int64_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_int64;
+}
- return_cache->is_skipped = g_callable_info_skip_return (callable_info);
- callable_cache->return_cache = return_cache;
- g_base_info_unref (return_info);
+static void
+_arg_cache_to_py_int64_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_int64;
+}
- callable_cache->user_data_index = -1;
+static void
+_arg_cache_from_py_uint64_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_uint64;
+}
- for (i = 0, arg_index = callable_cache->args_offset;
- (gsize)arg_index < _pygi_callable_cache_args_len (callable_cache);
- i++, arg_index++) {
- PyGIArgCache *arg_cache = NULL;
- GIArgInfo *arg_info;
- PyGIDirection direction;
+static void
+_arg_cache_to_py_uint64_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_uint64;
+}
- arg_info = g_callable_info_get_arg (callable_info, i);
+static void
+_arg_cache_from_py_float_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_float;
+}
- /* This only happens when dealing with callbacks */
- if (g_arg_info_get_closure (arg_info) == i) {
- callable_cache->user_data_index = i;
+static void
+_arg_cache_to_py_float_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_float;
+}
- arg_cache = pygi_arg_cache_alloc ();
- _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
+static void
+_arg_cache_from_py_double_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_double;
+}
- direction = _pygi_get_direction (callable_cache, GI_DIRECTION_IN);
- arg_cache->direction = direction;
- arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
- arg_cache->c_arg_index = i;
- arg_cache->is_pointer = TRUE;
+static void
+_arg_cache_to_py_double_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_double;
+}
- } else {
- GITypeInfo *type_info;
-
- direction = _pygi_get_direction (callable_cache,
- g_arg_info_get_direction (arg_info));
- type_info = g_arg_info_get_type (arg_info);
-
- /* must be an child arg filled in by its owner
- * and continue
- * fill in it's c_arg_index, add to the in count
- */
- arg_cache = _pygi_callable_cache_get_arg (callable_cache, arg_index);
- if (arg_cache != NULL) {
- /* ensure c_arg_index always aligns with callable_cache->args_cache
- * and all of the various PyGIInvokeState arrays. */
- arg_cache->c_arg_index = 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++;
- }
+static void
+_arg_cache_from_py_unichar_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_unichar;
+}
- if (direction & PYGI_DIRECTION_TO_PYTHON) {
- callable_cache->n_to_py_args++;
- }
+static void
+_arg_cache_to_py_unichar_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_unichar;
+}
- arg_cache->type_tag = g_type_info_get_tag (type_info);
+static void
+_arg_cache_from_py_gtype_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_gtype;
+}
- } else {
- GITransfer transfer;
- gssize py_arg_index = -1;
+static void
+_arg_cache_to_py_gtype_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_gtype;
+}
- transfer = g_arg_info_get_ownership_transfer (arg_info);
+static void
+_arg_cache_from_py_utf8_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_utf8;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_utf8;
+}
- if (direction & PYGI_DIRECTION_FROM_PYTHON) {
- py_arg_index = callable_cache->n_py_args;
- callable_cache->n_py_args++;
- }
+static void
+_arg_cache_to_py_utf8_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_utf8;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
+}
- arg_cache =
- pygi_arg_cache_new (type_info,
- arg_info,
- transfer,
- direction,
- callable_cache,
- arg_index,
- py_arg_index);
-
- if (arg_cache == NULL) {
- g_base_info_unref( (GIBaseInfo *)type_info);
- g_base_info_unref( (GIBaseInfo *)arg_info);
- return FALSE;
- }
+static void
+_arg_cache_from_py_filename_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_filename;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_utf8;
+}
+static void
+_arg_cache_to_py_filename_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_filename;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
+}
- if (direction & PYGI_DIRECTION_TO_PYTHON) {
- callable_cache->n_to_py_args++;
+static gboolean
+_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
+ PyGICallableCache *callable_cache,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ gssize arg_index)
+{
+ PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ seq_cache->array_type = g_type_info_get_array_type (type_info);
- callable_cache->to_py_args =
- g_slist_append (callable_cache->to_py_args, arg_cache);
- }
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
- _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
- }
+ if (seq_cache->len_arg_index >= 0) {
+ PyGIArgCache *child_cache =
+ callable_cache->args_cache[seq_cache->len_arg_index];
- g_base_info_unref (type_info);
+ if (child_cache == NULL) {
+ child_cache = _arg_cache_alloc ();
+ } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
+ child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
+ return TRUE;
}
- /* Ensure arguments always have a name when available */
- arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
-
- g_base_info_unref ( (GIBaseInfo *)arg_info);
+ if (seq_cache->len_arg_index < arg_index)
+ child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE;
+ else
+ child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
- }
+ child_cache->direction = direction;
+ child_cache->to_py_marshaller = NULL;
+ child_cache->from_py_marshaller = 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);
+ callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
}
- callable_cache->n_py_required_args = 0;
- callable_cache->user_data_varargs_index = -1;
- last_explicit_arg_index = -1;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
- /* Reverse loop through all the arguments to setup arg_name_list/hash
- * and find the number of required arguments */
- for (i=((gssize)_pygi_callable_cache_args_len (callable_cache))-1; i >= 0; i--) {
- PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache, i);
+ return TRUE;
+}
- if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD &&
- arg_cache->meta_type != PYGI_META_ARG_TYPE_CLOSURE &&
- arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
+static gboolean
+_arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
+ PyGICallableCache *callable_cache,
+ GITypeInfo *type_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ gssize arg_index)
+{
+ PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
- /* Setup arg_name_list and arg_name_hash */
- gpointer arg_name = (gpointer)arg_cache->arg_name;
- callable_cache->arg_name_list = g_slist_prepend (callable_cache->arg_name_list,
- arg_name);
- if (arg_name != NULL) {
- g_hash_table_insert (callable_cache->arg_name_hash,
- arg_name,
- GINT_TO_POINTER(i));
- }
+ seq_cache->array_type = g_type_info_get_array_type (type_info);
- /* The first tail argument without a default will force all the preceding
- * argument defaults off. This limits support of default args to the
- * tail of an args list.
- */
- if (callable_cache->n_py_required_args > 0) {
- arg_cache->has_default = FALSE;
- callable_cache->n_py_required_args += 1;
- } else if (!arg_cache->has_default) {
- callable_cache->n_py_required_args += 1;
- }
+ 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_to_py_child_args++;
- if (last_explicit_arg_index == -1) {
- last_explicit_arg_index = i;
+ if (child_cache != NULL) {
+ callable_cache->to_py_args =
+ g_slist_remove (callable_cache->to_py_args, child_cache);
- /* If the last "from python" argument in the args list is a child
- * with pyarg (currently only callback user_data). Set it to eat
- * variable args in the callable cache.
- */
- if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG)
- callable_cache->user_data_varargs_index = i;
- }
+ if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
+ child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE)
+ return TRUE;
+ } else {
+ child_cache = _arg_cache_alloc ();
}
- }
- if (!return_cache->is_skipped && return_cache->type_tag != GI_TYPE_TAG_VOID) {
- callable_cache->has_return = TRUE;
- }
+ child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+ child_cache->direction = direction;
+ child_cache->to_py_marshaller = NULL;
+ child_cache->from_py_marshaller = NULL;
- tuple_names = PyList_New (0);
- if (callable_cache->has_return) {
- PyList_Append (tuple_names, Py_None);
+ callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
}
- arg_cache_item = callable_cache->to_py_args;
- while (arg_cache_item) {
- const gchar *arg_name = ((PyGIArgCache *)arg_cache_item->data)->arg_name;
- PyObject *arg_string = PYGLIB_PyUnicode_FromString (arg_name);
- PyList_Append (tuple_names, arg_string);
- Py_DECREF (arg_string);
- arg_cache_item = arg_cache_item->next;
- }
+ return TRUE;
+}
- /* No need to create a tuple type if there aren't multiple values */
- if (PyList_Size (tuple_names) > 1) {
- resulttuple_type = pygi_resulttuple_new_type (tuple_names);
- if (resulttuple_type == NULL) {
- Py_DECREF (tuple_names);
- return FALSE;
- } else {
- callable_cache->resulttuple_type = resulttuple_type;
- }
- }
- Py_DECREF (tuple_names);
+static void
+_arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
+}
- return TRUE;
+static void
+_arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
}
static void
-_callable_cache_deinit_real (PyGICallableCache *cache)
+_arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
{
- g_clear_pointer (&cache->to_py_args, g_slist_free);
- g_clear_pointer (&cache->arg_name_list, g_slist_free);
- g_clear_pointer (&cache->arg_name_hash, g_hash_table_unref);
- g_clear_pointer (&cache->args_cache, g_ptr_array_unref);
- Py_CLEAR (cache->resulttuple_type);
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
+}
- g_clear_pointer (&cache->return_cache, pygi_arg_cache_free);
+static void
+_arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
}
-static gboolean
-_callable_cache_init (PyGICallableCache *cache,
- GICallableInfo *callable_info)
+static void
+_arg_cache_from_py_ghash_setup (PyGIArgCache *arg_cache)
{
- gint n_args;
- GIBaseInfo *container;
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_ghash;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_ghash;
+}
- if (cache->deinit == NULL)
- cache->deinit = _callable_cache_deinit_real;
+static void
+_arg_cache_to_py_ghash_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_ghash;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_ghash;
+}
- if (cache->generate_args_cache == NULL)
- cache->generate_args_cache = _callable_cache_generate_args_cache_real;
+static void
+_arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
+ arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+}
- cache->name = g_base_info_get_name ((GIBaseInfo *) callable_info);
- cache->namespace = g_base_info_get_namespace ((GIBaseInfo *) callable_info);
- container = g_base_info_get_container ((GIBaseInfo *) callable_info);
- cache->container_name = NULL;
- /* https://bugzilla.gnome.org/show_bug.cgi?id=709456 */
- if (container != NULL && g_base_info_get_type (container) != GI_INFO_TYPE_TYPE) {
- cache->container_name = g_base_info_get_name (container);
- }
- cache->throws = g_callable_info_can_throw_gerror ((GIBaseInfo *) callable_info);
-
- if (g_base_info_is_deprecated (callable_info)) {
- const gchar *deprecated = g_base_info_get_attribute (callable_info, "deprecated");
- gchar *warning;
- gchar *full_name = pygi_callable_cache_get_full_name (cache);
- if (deprecated != NULL)
- warning = g_strdup_printf ("%s is deprecated: %s",
- full_name,
- deprecated);
- else
- warning = g_strdup_printf ("%s is deprecated",
- full_name);
- g_free (full_name);
- PyErr_WarnEx (PyExc_DeprecationWarning, warning, 0);
- g_free (warning);
- }
+static void
+_arg_cache_to_py_gerror_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
+ arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+}
- n_args = cache->args_offset + g_callable_info_get_n_args (callable_info);
+static void
+_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct;
+}
- if (n_args >= 0) {
- cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify) pygi_arg_cache_free);
- g_ptr_array_set_size (cache->args_cache, n_args);
- }
+static void
+_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct;
+}
- if (!cache->generate_args_cache (cache, callable_info)) {
- _callable_cache_deinit_real (cache);
- return FALSE;
- }
+static void
+_arg_cache_from_py_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->from_py_marshaller = _pygi_marshal_from_py_interface_struct;
+
+ if (iface_cache->g_type == G_TYPE_VALUE)
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
+ else if (iface_cache->is_foreign)
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
+}
- return TRUE;
+static void
+_arg_cache_to_py_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->to_py_marshaller = _pygi_marshal_to_py_interface_struct;
+
+ if (iface_cache->is_foreign)
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
}
-gchar *
-pygi_callable_cache_get_full_name (PyGICallableCache *cache)
+static void
+_arg_cache_from_py_interface_object_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
{
- if (cache->container_name != NULL) {
- return g_strjoin (".",
- cache->namespace,
- cache->container_name,
- cache->name,
- NULL);
- } else {
- return g_strjoin (".",
- cache->namespace,
- cache->name,
- NULL);
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_object;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
+}
+
+static void
+_arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_object;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
+}
+
+static void
+_arg_cache_from_py_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;
+ user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
+ 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;
+ destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
+ callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
}
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
}
-void
-pygi_callable_cache_free (PyGICallableCache *cache)
+static void
+_arg_cache_to_py_interface_callback_setup (void)
{
- cache->deinit (cache);
- g_free (cache);
+ PyErr_Format(PyExc_NotImplementedError,
+ "Callback returns are not supported");
}
-/* PyGIFunctionCache */
+static void
+_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
+}
-static PyObject *
-_function_cache_invoke_real (PyGIFunctionCache *function_cache,
- PyGIInvokeState *state,
- PyObject *py_args,
- PyObject *py_kwargs)
+static void
+_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
{
- return pygi_invoke_c_callable (function_cache, state,
- py_args, py_kwargs);
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
}
static void
-_function_cache_deinit_real (PyGICallableCache *callable_cache)
+_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
{
- g_function_invoker_destroy (&((PyGIFunctionCache *) callable_cache)->invoker);
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
+}
- _callable_cache_deinit_real (callable_cache);
+static void
+_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
}
-static gboolean
-_function_cache_init (PyGIFunctionCache *function_cache,
- GICallableInfo *callable_info)
+PyGIArgCache *
+_arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
+ PyGICallableCache *callable_cache,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ gssize c_arg_index,
+ gssize py_arg_index)
{
- PyGICallableCache *callable_cache = (PyGICallableCache *) function_cache;
- GIFunctionInvoker *invoker = &function_cache->invoker;
- GError *error = NULL;
+ PyGIInterfaceCache *iface_cache = NULL;
+ PyGIArgCache *arg_cache = NULL;
+ gssize child_offset = 0;
+ GIInfoType info_type;
- callable_cache->calling_context = PYGI_CALLING_CONTEXT_IS_FROM_PY;
+ if (callable_cache != NULL)
+ child_offset =
+ (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
+ callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
- if (callable_cache->deinit == NULL)
- callable_cache->deinit = _function_cache_deinit_real;
+ info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);
- if (function_cache->invoke == NULL)
- function_cache->invoke = _function_cache_invoke_real;
+ /* Callbacks are special cased */
+ if (info_type != GI_INFO_TYPE_CALLBACK) {
+ iface_cache = _interface_cache_new (iface_info);
- if (!_callable_cache_init (callable_cache, callable_info))
- return FALSE;
+ arg_cache = (PyGIArgCache *)iface_cache;
+ if (arg_cache == NULL)
+ return NULL;
+ }
- /* Set by PyGICCallbackCache and PyGIVFuncCache */
- if (invoker->native_address == NULL) {
- if (g_function_info_prep_invoker ((GIFunctionInfo *) callable_info,
- invoker,
- &error)) {
- return TRUE;
- }
- } else {
- if (g_function_invoker_new_for_address (invoker->native_address,
- (GIFunctionInfo *) callable_info,
- invoker,
- &error)) {
- return TRUE;
- }
+ switch (info_type) {
+ case GI_INFO_TYPE_UNION:
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
+
+ break;
+ case GI_INFO_TYPE_STRUCT:
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+ break;
+ case GI_INFO_TYPE_OBJECT:
+ case GI_INFO_TYPE_INTERFACE:
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
+
+ break;
+ case GI_INFO_TYPE_BOXED:
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_interface_struct_setup (arg_cache,
+ iface_info,
+ transfer);
+ break;
+ case GI_INFO_TYPE_CALLBACK:
+ {
+ PyGICallbackCache *callback_cache;
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
+ _arg_cache_to_py_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 == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_interface_callback_setup (arg_cache, callable_cache);
+
+ break;
+ }
+ case GI_INFO_TYPE_ENUM:
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
+
+ break;
+ case GI_INFO_TYPE_FLAGS:
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
+
+ break;
+ default:
+ g_assert_not_reached ();
}
- if (!pygi_error_check (&error)) {
- PyErr_Format (PyExc_RuntimeError,
- "unknown error creating invoker for %s",
- g_base_info_get_name ((GIBaseInfo *) callable_info));
+ 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;
+ }
}
- _callable_cache_deinit_real (callable_cache);
- return FALSE;
+ return arg_cache;
}
-PyGIFunctionCache *
-pygi_function_cache_new (GICallableInfo *info)
+PyGIArgCache *
+_arg_cache_new (GITypeInfo *type_info,
+ PyGICallableCache *callable_cache,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ gssize c_arg_index,
+ gssize py_arg_index)
{
- PyGIFunctionCache *function_cache;
+ PyGIArgCache *arg_cache = NULL;
+ gssize child_offset = 0;
+ GITypeTag type_tag;
- function_cache = g_new0 (PyGIFunctionCache, 1);
+ type_tag = g_type_info_get_tag (type_info);
- if (!_function_cache_init (function_cache, info)) {
- g_free (function_cache);
- return NULL;
- }
+ if (callable_cache != NULL)
+ child_offset =
+ (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
+ callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
- return function_cache;
-}
+ switch (type_tag) {
+ case GI_TYPE_TAG_VOID:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
-PyObject *
-pygi_function_cache_invoke (PyGIFunctionCache *function_cache,
- PyObject *py_args,
- PyObject *py_kwargs)
-{
- PyGIInvokeState state = { 0, };
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_void_setup (arg_cache);
- return function_cache->invoke (function_cache, &state,
- py_args, py_kwargs);
-}
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_void_setup (arg_cache);
-/* PyGICCallbackCache */
+ break;
+ case GI_TYPE_TAG_BOOLEAN:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
-PyGIFunctionCache *
-pygi_ccallback_cache_new (GICallableInfo *info,
- GCallback function_ptr)
-{
- PyGICCallbackCache *ccallback_cache;
- PyGIFunctionCache *function_cache;
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_boolean_setup (arg_cache);
- ccallback_cache = g_new0 (PyGICCallbackCache, 1);
- function_cache = (PyGIFunctionCache *) ccallback_cache;
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_boolean_setup (arg_cache);
- function_cache->invoker.native_address = function_ptr;
+ break;
+ case GI_TYPE_TAG_INT8:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
- if (!_function_cache_init (function_cache, info)) {
- g_free (ccallback_cache);
- return NULL;
- }
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_int8_setup (arg_cache);
- return function_cache;
-}
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_int8_setup (arg_cache);
-PyObject *
-pygi_ccallback_cache_invoke (PyGICCallbackCache *ccallback_cache,
- PyObject *py_args,
- PyObject *py_kwargs,
- gpointer user_data)
-{
- PyGIFunctionCache *function_cache = (PyGIFunctionCache *) ccallback_cache;
- PyGIInvokeState state = { 0, };
+ break;
+ case GI_TYPE_TAG_UINT8:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
- state.user_data = user_data;
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_uint8_setup (arg_cache);
- return function_cache->invoke (function_cache, &state,
- py_args, py_kwargs);
-}
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_uint8_setup (arg_cache);
-/* PyGIConstructorCache */
+ break;
+ case GI_TYPE_TAG_INT16:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
-static PyObject *
-_constructor_cache_invoke_real (PyGIFunctionCache *function_cache,
- PyGIInvokeState *state,
- PyObject *py_args,
- PyObject *py_kwargs)
-{
- PyGICallableCache *cache = (PyGICallableCache *) function_cache;
- PyObject *constructor_class;
- PyObject *ret;
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_int16_setup (arg_cache);
- constructor_class = PyTuple_GetItem (py_args, 0);
- if (constructor_class == NULL) {
- gchar *full_name = pygi_callable_cache_get_full_name (cache);
- PyErr_Clear ();
- PyErr_Format (PyExc_TypeError,
- "Constructors require the class to be passed in as an argument, "
- "No arguments passed to the %s constructor.",
- full_name);
- g_free (full_name);
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_int16_setup (arg_cache);
- return FALSE;
- }
+ break;
+ case GI_TYPE_TAG_UINT16:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
- py_args = PyTuple_GetSlice (py_args, 1, PyTuple_Size (py_args));
- ret = _function_cache_invoke_real (function_cache, state,
- py_args, py_kwargs);
- Py_DECREF (py_args);
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_uint16_setup (arg_cache);
- if (ret == NULL || cache->return_cache->is_skipped)
- return ret;
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_uint16_setup (arg_cache);
+ break;
+ case GI_TYPE_TAG_INT32:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
- if (ret != Py_None) {
- if (!PyTuple_Check (ret))
- return ret;
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_int32_setup (arg_cache);
- if (PyTuple_GET_ITEM (ret, 0) != Py_None)
- return ret;
- }
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_int32_setup (arg_cache);
- PyErr_SetString (PyExc_TypeError, "constructor returned NULL");
+ break;
+ case GI_TYPE_TAG_UINT32:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
- Py_DECREF (ret);
- return NULL;
-}
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_uint32_setup (arg_cache);
-PyGIFunctionCache *
-pygi_constructor_cache_new (GICallableInfo *info)
-{
- PyGIConstructorCache *constructor_cache;
- PyGIFunctionCache *function_cache;
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_uint32_setup (arg_cache);
- constructor_cache = g_new0 (PyGIConstructorCache, 1);
- function_cache = (PyGIFunctionCache *) constructor_cache;
+ break;
+ case GI_TYPE_TAG_INT64:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
- function_cache->invoke = _constructor_cache_invoke_real;
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_int64_setup (arg_cache);
- if (!_function_cache_init (function_cache, info)) {
- g_free (constructor_cache);
- return NULL;
- }
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_int64_setup (arg_cache);
- return function_cache;
-}
+ break;
+ case GI_TYPE_TAG_UINT64:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
-/* PyGIFunctionWithInstanceCache */
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_uint64_setup (arg_cache);
-static gboolean
-_function_with_instance_cache_generate_args_cache_real (PyGICallableCache *callable_cache,
- GICallableInfo *callable_info)
-{
- GIInterfaceInfo *interface_info;
- PyGIArgCache *instance_cache;
- GITransfer transfer;
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_uint64_setup (arg_cache);
- interface_info = g_base_info_get_container ((GIBaseInfo *) callable_info);
- transfer = g_callable_info_get_instance_ownership_transfer (callable_info);
+ break;
+ case GI_TYPE_TAG_FLOAT:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
- instance_cache =
- _arg_cache_new_for_interface (interface_info,
- NULL,
- NULL,
- transfer,
- PYGI_DIRECTION_FROM_PYTHON,
- callable_cache);
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_float_setup (arg_cache);
- if (instance_cache == NULL)
- return FALSE;
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_float_setup (arg_cache);
- /* Because we are not supplied a GITypeInfo for instance arguments,
- * assume some defaults. */
- instance_cache->is_pointer = TRUE;
- instance_cache->py_arg_index = 0;
- instance_cache->c_arg_index = 0;
+ break;
+ case GI_TYPE_TAG_DOUBLE:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
- _pygi_callable_cache_set_arg (callable_cache, 0, instance_cache);
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_double_setup (arg_cache);
- callable_cache->n_py_args++;
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_double_setup (arg_cache);
- return _callable_cache_generate_args_cache_real (callable_cache,
- callable_info);
-}
+ break;
+ case GI_TYPE_TAG_UNICHAR:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
-static gboolean
-_function_with_instance_cache_init (PyGIFunctionWithInstanceCache *fwi_cache,
- GICallableInfo *info)
-{
- PyGICallableCache *callable_cache = (PyGICallableCache *) fwi_cache;
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_unichar_setup (arg_cache);
- callable_cache->args_offset += 1;
- callable_cache->generate_args_cache = _function_with_instance_cache_generate_args_cache_real;
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_unichar_setup (arg_cache);
- return _function_cache_init ((PyGIFunctionCache *) fwi_cache, info);
-}
+ break;
+ case GI_TYPE_TAG_GTYPE:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
-/* PyGIMethodCache */
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_gtype_setup (arg_cache);
-PyGIFunctionCache *
-pygi_method_cache_new (GICallableInfo *info)
-{
- PyGIMethodCache *method_cache;
- PyGIFunctionWithInstanceCache *fwi_cache;
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_gtype_setup (arg_cache);
- method_cache = g_new0 (PyGIMethodCache, 1);
- fwi_cache = (PyGIFunctionWithInstanceCache *) method_cache;
+ break;
+ case GI_TYPE_TAG_UTF8:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
- if (!_function_with_instance_cache_init (fwi_cache, info)) {
- g_free (method_cache);
- return NULL;
- }
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_utf8_setup (arg_cache, transfer);
- return (PyGIFunctionCache *) method_cache;
-}
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_utf8_setup (arg_cache, transfer);
-/* PyGIVFuncCache */
+ break;
+ case GI_TYPE_TAG_FILENAME:
+ arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ break;
-static PyObject *
-_vfunc_cache_invoke_real (PyGIFunctionCache *function_cache,
- PyGIInvokeState *state,
- PyObject *py_args,
- PyObject *py_kwargs)
-{
- PyGIVFuncCache *vfunc_cache = (PyGIVFuncCache *) function_cache;
- PyObject *py_gtype;
- GType implementor_gtype;
- GError *error = NULL;
- PyObject *ret;
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_filename_setup (arg_cache, transfer);
- py_gtype = PyTuple_GetItem (py_args, 0);
- if (py_gtype == NULL) {
- PyErr_SetString (PyExc_TypeError,
- "need the GType of the implementor class");
- return FALSE;
- }
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_filename_setup (arg_cache, transfer);
- implementor_gtype = pyg_type_from_object (py_gtype);
- if (implementor_gtype == G_TYPE_INVALID)
- return FALSE;
+ break;
+ case GI_TYPE_TAG_ARRAY:
+ {
+ PyGISequenceCache *seq_cache =
+ _sequence_cache_new (type_info,
+ direction,
+ transfer,
+ child_offset);
- /* vfunc addresses are pulled into the state at call time and cannot be
- * cached because the call site can specify a different portion of the
- * class hierarchy. e.g. Object.do_func vs. SubObject.do_func might
- * retrieve a different vfunc address but GI gives us the same vfunc info.
- */
- state->function_ptr = g_vfunc_info_get_address ((GIVFuncInfo *) vfunc_cache->info,
- implementor_gtype,
- &error);
- if (pygi_error_check (&error)) {
- return FALSE;
+ arg_cache = (PyGIArgCache *)seq_cache;
+ if (arg_cache == NULL)
+ break;
+
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_array_setup (arg_cache,
+ callable_cache,
+ type_info,
+ transfer,
+ direction,
+ c_arg_index);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_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 &&
+ callable_cache->args_cache[seq_cache->len_arg_index]->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
+ gssize i;
+ PyGIArgCache *child_cache =
+ callable_cache->args_cache[seq_cache->len_arg_index];
+
+ child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+ 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 == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_glist_setup (arg_cache, transfer);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_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 == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_gslist_setup (arg_cache, transfer);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_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 == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_ghash_setup (arg_cache);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
+ _arg_cache_to_py_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 == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_from_py_gerror_setup (arg_cache);
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+ _arg_cache_to_py_gerror_setup (arg_cache);
+
+ break;
}
- py_args = PyTuple_GetSlice (py_args, 1, PyTuple_Size (py_args));
- ret = _function_cache_invoke_real (function_cache, state,
- py_args, py_kwargs);
- Py_DECREF (py_args);
+ 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 ret;
+ return arg_cache;
}
static void
-_vfunc_cache_deinit_real (PyGICallableCache *callable_cache)
+_arg_name_list_generate (PyGICallableCache *callable_cache)
{
- g_base_info_unref (((PyGIVFuncCache *) callable_cache)->info);
+ GSList * arg_name_list = NULL;
+ int i;
+
+ 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 (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->meta_type != PYGI_META_ARG_TYPE_CLOSURE &&
+ (arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON ||
+ arg_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL)) {
+
+ 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);
+ }
+ }
+ }
- _function_cache_deinit_real (callable_cache);
+ callable_cache->arg_name_list = g_slist_reverse (arg_name_list);
}
-PyGIFunctionCache *
-pygi_vfunc_cache_new (GICallableInfo *info)
+/* Generate the cache for the callable's arguments */
+static gboolean
+_args_cache_generate (GICallableInfo *callable_info,
+ PyGICallableCache *callable_cache)
{
- PyGIVFuncCache *vfunc_cache;
- PyGIFunctionCache *function_cache;
- PyGIFunctionWithInstanceCache *fwi_cache;
+ gssize arg_index = 0;
+ gssize i;
+ GITypeInfo *return_info;
+ GITransfer return_transfer;
+ PyGIArgCache *return_cache;
+ PyGIDirection return_direction;
- vfunc_cache = g_new0 (PyGIVFuncCache, 1);
- function_cache = (PyGIFunctionCache *) vfunc_cache;
- fwi_cache = (PyGIFunctionWithInstanceCache *) vfunc_cache;
+ /* determine if we are marshalling the return to or from python */
+ if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
+ return_direction = PYGI_DIRECTION_FROM_PYTHON;
+ else
+ return_direction = PYGI_DIRECTION_TO_PYTHON;
- ((PyGICallableCache *) vfunc_cache)->deinit = _vfunc_cache_deinit_real;
+ /* 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,
+ return_direction,
+ -1,
+ -1);
- /* This must be non-NULL for _function_cache_init() to create the
- * invoker, the real address will be set in _vfunc_cache_invoke_real().
- */
- function_cache->invoker.native_address = (gpointer) 0xdeadbeef;
+ return_cache->is_skipped = g_callable_info_skip_return (callable_info);
+ callable_cache->return_cache = return_cache;
+ g_base_info_unref (return_info);
- function_cache->invoke = _vfunc_cache_invoke_real;
+ /* 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;
+ PyGIDirection instance_direction;
- if (!_function_with_instance_cache_init (fwi_cache, info)) {
- g_free (vfunc_cache);
- return NULL;
- }
+ instance_direction = PYGI_DIRECTION_FROM_PYTHON;
- /* Required by _vfunc_cache_invoke_real() */
- vfunc_cache->info = g_base_info_ref ((GIBaseInfo *) info);
- return function_cache;
-}
+ interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
-/* PyGIClosureCache */
+ instance_cache =
+ _arg_cache_new_for_interface (interface_info,
+ callable_cache,
+ NULL,
+ GI_TRANSFER_NOTHING,
+ instance_direction,
+ arg_index,
+ 0);
-PyGIClosureCache *
-pygi_closure_cache_new (GICallableInfo *info)
-{
- gssize i;
- PyGIClosureCache *closure_cache;
- PyGICallableCache *callable_cache;
+ /* FIXME: marshal interfaces from_py */
+ instance_cache->from_py_marshaller = _pygi_marshal_from_py_interface_instance;
+ g_base_info_unref ( (GIBaseInfo *)interface_info);
- closure_cache = g_new0 (PyGIClosureCache, 1);
- callable_cache = (PyGICallableCache *) closure_cache;
+ if (instance_cache == NULL)
+ return FALSE;
- callable_cache->calling_context = PYGI_CALLING_CONTEXT_IS_FROM_C;
+ callable_cache->args_cache[arg_index] = instance_cache;
- if (!_callable_cache_init (callable_cache, info)) {
- g_free (closure_cache);
- return NULL;
+ arg_index++;
+ callable_cache->n_from_py_args++;
+ callable_cache->n_py_args++;
}
- /* For backwards compatibility closures include the array's length.
- *
- * See: https://bugzilla.gnome.org/show_bug.cgi?id=652115
- */
- for (i = 0; (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) {
- PyGIArgCache *arg_cache;
- PyGIArgGArray *garray_cache;
- PyGIArgCache *len_arg_cache;
-
- arg_cache = g_ptr_array_index (callable_cache->args_cache, i);
- if (arg_cache->type_tag != GI_TYPE_TAG_ARRAY)
+
+ for (i=0; arg_index < callable_cache->n_args; arg_index++, i++) {
+ PyGIArgCache *arg_cache = NULL;
+ GIArgInfo *arg_info;
+ GITypeInfo *type_info;
+ GIDirection gi_direction;
+ PyGIDirection 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);
+
+ if (g_arg_info_get_closure (arg_info) == i) {
+
+ arg_cache = _arg_cache_alloc ();
+ callable_cache->args_cache[arg_index] = arg_cache;
+
+ arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
+ arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
+ arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
+ arg_cache->c_arg_index = i;
+
+ callable_cache->n_from_py_args++;
+
+ g_base_info_unref ( (GIBaseInfo *)arg_info);
+
continue;
+ }
- garray_cache = (PyGIArgGArray *) arg_cache;
- if (garray_cache->len_arg_index == -1)
+ /* For vfuncs and callbacks our marshalling directions
+ are reversed */
+ gi_direction = g_arg_info_get_direction (arg_info);
+ if (gi_direction == GI_DIRECTION_INOUT) {
+ direction = PYGI_DIRECTION_BIDIRECTIONAL;
+ } else if (gi_direction == GI_DIRECTION_IN) {
+ direction = PYGI_DIRECTION_FROM_PYTHON;
+ if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
+ direction = PYGI_DIRECTION_TO_PYTHON;
+ } else {
+ direction = PYGI_DIRECTION_TO_PYTHON;
+ if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
+ direction = PYGI_DIRECTION_FROM_PYTHON;
+ }
+
+ 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
+ * and continue
+ * fill in it's c_arg_index, add to the in count
+ */
+ 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 == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
+ arg_cache->c_arg_index = callable_cache->n_from_py_args;
+ callable_cache->n_from_py_args++;
+ }
+
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
+ callable_cache->n_to_py_args++;
+ callable_cache->n_to_py_child_args++;
+ }
+
+ g_base_info_unref ( (GIBaseInfo *)arg_info);
continue;
+ }
- len_arg_cache = g_ptr_array_index (callable_cache->args_cache,
- garray_cache->len_arg_index);
- len_arg_cache->meta_type = PYGI_META_ARG_TYPE_PARENT;
- }
+ if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
+ py_arg_index = callable_cache->n_py_args;
+ callable_cache->n_from_py_args++;
+ callable_cache->n_py_args++;
+ }
- /* Prevent guessing multiple user data arguments.
- * This is required because some versions of GI
- * do not recognize user_data/data arguments correctly.
- */
- if (callable_cache->user_data_index == -1) {
- for (i = 0; (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) {
- PyGIArgCache *arg_cache;
+ arg_cache =
+ _arg_cache_new (type_info,
+ callable_cache,
+ arg_info,
+ transfer,
+ direction,
+ arg_index,
+ py_arg_index);
- arg_cache = g_ptr_array_index (callable_cache->args_cache, i);
+ if (arg_cache == NULL)
+ goto arg_err;
- if (arg_cache->direction == PYGI_DIRECTION_TO_PYTHON &&
- arg_cache->type_tag == GI_TYPE_TAG_VOID &&
- arg_cache->is_pointer) {
+ 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;
- callable_cache->user_data_index = i;
- break;
- }
+ if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
+ callable_cache->n_to_py_args++;
+
+ if (arg_cache == NULL)
+ goto arg_err;
+
+ callable_cache->to_py_args =
+ g_slist_append (callable_cache->to_py_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, gboolean is_ccallback)
+{
+ 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) {
+ if (is_ccallback)
+ cache->function_type = PYGI_FUNCTION_TYPE_CCALLBACK;
+ else
+ cache->function_type = PYGI_FUNCTION_TYPE_CALLBACK;
+ } else {
+ cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
}
- return closure_cache;
+ 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;
}