/* -*- Mode: C; c-basic-offset: 4 -*- * vim: tabstop=4 shiftwidth=4 expandtab * * Copyright (C) 2011 John (J5) Palmieri * Copyright (C) 2013 Simon Feltman * * 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, see . */ #ifndef __PYGI_CACHE_H__ #define __PYGI_CACHE_H__ #include #include #include #include "pygi-invoke-state-struct.h" G_BEGIN_DECLS typedef struct _PyGIArgCache PyGIArgCache; typedef struct _PyGICallableCache PyGICallableCache; typedef struct _PyGIFunctionCache PyGIFunctionCache; typedef struct _PyGIVFuncCache PyGIVFuncCache; typedef PyGIFunctionCache PyGICCallbackCache; typedef PyGIFunctionCache PyGIConstructorCache; typedef PyGIFunctionCache PyGIFunctionWithInstanceCache; typedef PyGIFunctionCache PyGIMethodCache; typedef PyGICallableCache PyGIClosureCache; typedef gboolean (*PyGIMarshalFromPyFunc) (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data); typedef PyObject *(*PyGIMarshalToPyFunc) (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg, gpointer *cleanup_data); typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, gpointer data, gboolean was_processed); typedef void (*PyGIMarshalToPyCleanupFunc) (PyGIInvokeState *state, PyGIArgCache *arg_cache, gpointer cleanup_data, gpointer data, gboolean was_processed); /* Argument meta types denote how we process the argument: * - PYGI_META_ARG_TYPE_PARENT - parents may or may not have children * but are always processed via the normal marshaller for their * actual GI type. If they have children the marshaller will * also handle marshalling the children. * - PYGI_META_ARG_TYPE_CHILD - Children without python argument are * ignored by the marshallers and handled directly by their parents * marshaller. * - Children with pyargs (PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) are processed * the same as other child args but also have an index into the * python parameters passed to the invoker */ typedef enum { PYGI_META_ARG_TYPE_PARENT, PYGI_META_ARG_TYPE_CHILD, PYGI_META_ARG_TYPE_CHILD_WITH_PYARG, PYGI_META_ARG_TYPE_CLOSURE, } PyGIMetaArgType; /* * Argument direction types denotes how we marshal, * e.g. to Python or from Python or both. */ typedef enum { PYGI_DIRECTION_TO_PYTHON = 1 << 0, PYGI_DIRECTION_FROM_PYTHON = 1 << 1, PYGI_DIRECTION_BIDIRECTIONAL = PYGI_DIRECTION_TO_PYTHON | PYGI_DIRECTION_FROM_PYTHON } PyGIDirection; /* * In PyGI IN and OUT arguments mean different things depending on the context * of the callable, e.g. is it a callback that is being called from C or a * function that is being called from Python. */ typedef enum { PYGI_CALLING_CONTEXT_IS_FROM_C, PYGI_CALLING_CONTEXT_IS_FROM_PY } PyGICallingContext; struct _PyGIArgCache { const gchar *arg_name; PyGIMetaArgType meta_type; gboolean is_pointer; gboolean is_caller_allocates; gboolean is_skipped; gboolean allow_none; gboolean has_default; PyGIDirection direction; GITransfer transfer; GITypeTag type_tag; GITypeInfo *type_info; PyGIMarshalFromPyFunc from_py_marshaller; PyGIMarshalToPyFunc to_py_marshaller; PyGIMarshalCleanupFunc from_py_cleanup; PyGIMarshalToPyCleanupFunc to_py_cleanup; GDestroyNotify destroy_notify; gssize c_arg_index; gssize py_arg_index; /* Set when has_default is true. */ GIArgument default_value; }; typedef struct _PyGISequenceCache { PyGIArgCache arg_cache; PyGIArgCache *item_cache; } PyGISequenceCache; typedef struct _PyGIArgGArray { PyGISequenceCache seq_cache; gssize fixed_size; gssize len_arg_index; gboolean is_zero_terminated; gsize item_size; GIArrayType array_type; } PyGIArgGArray; typedef struct _PyGIInterfaceCache { PyGIArgCache arg_cache; gboolean is_foreign; GType g_type; PyObject *py_type; GIInterfaceInfo *interface_info; gchar *type_name; } PyGIInterfaceCache; struct _PyGICallableCache { const gchar *name; const gchar *container_name; const gchar *namespace; PyGICallingContext calling_context; PyGIArgCache *return_cache; GPtrArray *args_cache; GSList *to_py_args; GSList *arg_name_list; /* for keyword arg matching */ GHashTable *arg_name_hash; gboolean throws; /* Index of user_data arg passed to a callable. */ gssize user_data_index; /* Index of user_data arg that can eat variable args passed to a callable. */ gssize user_data_varargs_index; /* Number of args already added */ gssize args_offset; /* Number of out args passed to g_function_info_invoke. * This is used for the length of PyGIInvokeState.out_values */ gssize n_to_py_args; /* If the callable return value gets used */ gboolean has_return; /* The type used for returning multiple values or NULL */ PyTypeObject* resulttuple_type; /* Number of out args for g_function_info_invoke that will be skipped * when marshaling to Python due to them being implicitly available * (list/array length). */ gssize n_to_py_child_args; /* Number of Python arguments expected for invoking the gi function. */ gssize n_py_args; /* Minimum number of args required to call the callable from Python. * This count does not include args with defaults. */ gssize n_py_required_args; void (*deinit) (PyGICallableCache *callable_cache); gboolean (*generate_args_cache) (PyGICallableCache *callable_cache, GICallableInfo *callable_info); }; struct _PyGIFunctionCache { PyGICallableCache callable_cache; /* An invoker with ffi_cif already setup */ GIFunctionInvoker invoker; PyObject *(*invoke) (PyGIFunctionCache *function_cache, PyGIInvokeState *state, PyObject *py_args, PyObject *py_kwargs); } ; struct _PyGIVFuncCache { PyGIFunctionWithInstanceCache fwi_cache; GIBaseInfo *info; }; gboolean pygi_arg_base_setup (PyGIArgCache *arg_cache, GITypeInfo *type_info, GIArgInfo *arg_info, /* may be NULL for return arguments */ GITransfer transfer, PyGIDirection direction); 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); 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); 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); PyGIArgCache * pygi_arg_cache_alloc (void); PyGIArgCache * pygi_arg_cache_new (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, PyGIDirection direction, PyGICallableCache *callable_cache, /* will be removed */ gssize c_arg_index, gssize py_arg_index); void pygi_arg_cache_free (PyGIArgCache *cache); void pygi_callable_cache_free (PyGICallableCache *cache); gchar * pygi_callable_cache_get_full_name (PyGICallableCache *cache); PyGIFunctionCache * pygi_function_cache_new (GICallableInfo *info); PyObject * pygi_function_cache_invoke (PyGIFunctionCache *function_cache, PyObject *py_args, PyObject *py_kwargs); PyGIFunctionCache * pygi_ccallback_cache_new (GICallableInfo *info, GCallback function_ptr); PyObject * pygi_ccallback_cache_invoke (PyGIFunctionCache *function_cache, PyObject *py_args, PyObject *py_kwargs, gpointer user_data); PyGIFunctionCache * pygi_constructor_cache_new (GICallableInfo *info); PyGIFunctionCache * pygi_method_cache_new (GICallableInfo *info); PyGIFunctionCache * pygi_vfunc_cache_new (GICallableInfo *info); PyGIClosureCache * pygi_closure_cache_new (GICallableInfo *info); inline static guint _pygi_callable_cache_args_len (PyGICallableCache *cache) { return ((cache)->args_cache)->len; } inline static PyGIArgCache * _pygi_callable_cache_get_arg (PyGICallableCache *cache, guint index) { return (PyGIArgCache *) g_ptr_array_index (cache->args_cache, index); } inline static void _pygi_callable_cache_set_arg (PyGICallableCache *cache, guint index, PyGIArgCache *arg_cache) { cache->args_cache->pdata[index] = arg_cache; } G_END_DECLS #endif /* __PYGI_CACHE_H__ */