From 2cddba811592fbb990322fbf2dce516ffd7e94cd Mon Sep 17 00:00:00 2001 From: Simon Feltman Date: Sat, 12 Oct 2013 12:39:20 -0700 Subject: cache refactoring: Move closure setup and marshaling into pygi-closure Move closure argument caching and marshaling fragments into pygi-closure.c. https://bugzilla.gnome.org/show_bug.cgi?id=709700 --- gi/pygi-cache.c | 111 ++-------------- gi/pygi-cache.h | 9 -- gi/pygi-closure.c | 314 +++++++++++++++++++++++++++++++++++++++++++++- gi/pygi-closure.h | 13 +- gi/pygi-marshal-cleanup.c | 14 --- gi/pygi-marshal-cleanup.h | 5 - gi/pygi-marshal-from-py.c | 160 ----------------------- gi/pygi-marshal-from-py.h | 6 - gi/pygi-marshal-to-py.c | 13 -- gi/pygi-marshal-to-py.h | 4 - 10 files changed, 333 insertions(+), 316 deletions(-) diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c index d91d8ab5..aded0256 100644 --- a/gi/pygi-cache.c +++ b/gi/pygi-cache.c @@ -31,6 +31,7 @@ #include "pygi-basictype.h" #include "pygi-list.h" #include "pygi-array.h" +#include "pygi-closure.h" #include "pygi-error.h" @@ -162,17 +163,6 @@ _sequence_cache_free_func (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) { @@ -248,28 +238,6 @@ pygi_arg_sequence_setup (PyGISequenceCache *sc, return TRUE; } -static PyGICallbackCache * -_callback_cache_new (GIArgInfo *arg_info, - GIInterfaceInfo *iface_info, - gssize child_offset) -{ - 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; -} - PyGIArgCache * _arg_cache_alloc (void) { @@ -334,38 +302,6 @@ _arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache, 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; - user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */ - _pygi_callable_cache_set_arg (callable_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; - _pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index, - destroy_arg_cache); - } - arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback; - arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback; -} - -static void -_arg_cache_to_py_interface_callback_setup (void) -{ - PyErr_Format(PyExc_NotImplementedError, - "Callback returns are not supported"); -} - static void _arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache, GITransfer transfer) @@ -404,45 +340,22 @@ _arg_cache_new_for_interface (GIInterfaceInfo *iface_info, PyGICallableCache *callable_cache) { 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; - info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info); - /* Callbacks are special cased */ - if (info_type == GI_INFO_TYPE_CALLBACK) { - PyGICallbackCache *callback_cache; - - if (direction & PYGI_DIRECTION_TO_PYTHON) { - _arg_cache_to_py_interface_callback_setup (); - return NULL; + 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); } - - callback_cache = - _callback_cache_new (arg_info, - iface_info, - child_offset); - - arg_cache = (PyGIArgCache *)callback_cache; - if (arg_cache == NULL) - return NULL; - - pygi_arg_base_setup (arg_cache, - type_info, - arg_info, - transfer, - direction); - - if (direction & PYGI_DIRECTION_FROM_PYTHON) - _arg_cache_from_py_interface_callback_setup (arg_cache, callable_cache); - - return arg_cache; - + default: + ; /* pass through to old model of setup */ } arg_cache = (PyGIArgCache *)_interface_cache_new (iface_info); diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h index 0629646a..d20cb9f9 100644 --- a/gi/pygi-cache.h +++ b/gi/pygi-cache.h @@ -155,15 +155,6 @@ typedef struct _PyGIInterfaceCache gchar *type_name; } PyGIInterfaceCache; -typedef struct _PyGICallbackCache -{ - PyGIArgCache arg_cache; - gssize user_data_index; - gssize destroy_notify_index; - GIScopeType scope; - GIInterfaceInfo *interface_info; -} PyGICallbackCache; - struct _PyGICallableCache { const gchar *name; diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c index 5df4713e..3dd73da9 100644 --- a/gi/pygi-closure.c +++ b/gi/pygi-closure.c @@ -14,12 +14,23 @@ * 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 + * License along with this library; if not, see . */ #include "pygi-private.h" +#include "pygi-closure.h" + + +typedef struct _PyGICallbackCache +{ + PyGIArgCache arg_cache; + gssize user_data_index; + gssize destroy_notify_index; + GIScopeType scope; + GIInterfaceInfo *interface_info; +} PyGICallbackCache; + +static PyGICClosure *global_destroy_notify; /* This maintains a list of closures which can be free'd whenever as they have been called. We will free them on the next @@ -669,3 +680,300 @@ _pygi_make_native_closure (GICallableInfo* info, return closure; } + +/* _pygi_destroy_notify_dummy: + * + * Dummy method used in the occasion when a method has a GDestroyNotify + * argument without user data. + */ +static void +_pygi_destroy_notify_dummy (gpointer data) { +} + +static void +_pygi_destroy_notify_callback_closure (ffi_cif *cif, + void *result, + void **args, + void *data) +{ + PyGICClosure *info = * (void**) (args[0]); + + g_assert (info); + + _pygi_invoke_closure_free (info); +} + +/* _pygi_destroy_notify_create: + * + * Method used in the occasion when a method has a GDestroyNotify + * argument with user data. + */ +static PyGICClosure* +_pygi_destroy_notify_create (void) +{ + if (!global_destroy_notify) { + + PyGICClosure *destroy_notify = g_slice_new0 (PyGICClosure); + GIBaseInfo* glib_destroy_notify; + + g_assert (destroy_notify); + + glib_destroy_notify = g_irepository_find_by_name (NULL, "GLib", "DestroyNotify"); + g_assert (glib_destroy_notify != NULL); + g_assert (g_base_info_get_type (glib_destroy_notify) == GI_INFO_TYPE_CALLBACK); + + destroy_notify->closure = g_callable_info_prepare_closure ( (GICallableInfo*) glib_destroy_notify, + &destroy_notify->cif, + _pygi_destroy_notify_callback_closure, + NULL); + + global_destroy_notify = destroy_notify; + } + + return global_destroy_notify; +} + +static gboolean +_pygi_marshal_from_py_interface_callback (PyGIInvokeState *state, + PyGICallableCache *callable_cache, + PyGIArgCache *arg_cache, + PyObject *py_arg, + GIArgument *arg, + gpointer *cleanup_data) +{ + GICallableInfo *callable_info; + PyGICClosure *closure; + PyGIArgCache *user_data_cache = NULL; + PyGIArgCache *destroy_cache = NULL; + PyGICallbackCache *callback_cache; + PyObject *py_user_data = NULL; + + callback_cache = (PyGICallbackCache *)arg_cache; + + if (callback_cache->user_data_index > 0) { + user_data_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->user_data_index); + if (user_data_cache->py_arg_index < state->n_py_in_args) { + /* py_user_data is a borrowed reference. */ + py_user_data = PyTuple_GetItem (state->py_in_args, user_data_cache->py_arg_index); + if (!py_user_data) + return FALSE; + /* NULL out user_data if it was not supplied and the default arg placeholder + * was used instead. + */ + if (py_user_data == _PyGIDefaultArgPlaceholder) { + py_user_data = NULL; + } else if (callable_cache->user_data_varargs_index < 0) { + /* For non-variable length user data, place the user data in a + * single item tuple which is concatenated to the callbacks arguments. + * This allows callback input arg marshaling to always expect a + * tuple for user data. Note the + */ + py_user_data = Py_BuildValue("(O)", py_user_data, NULL); + } else { + /* increment the ref borrowed from PyTuple_GetItem above */ + Py_INCREF (py_user_data); + } + } + } + + if (py_arg == Py_None) { + return TRUE; + } + + if (!PyCallable_Check (py_arg)) { + PyErr_Format (PyExc_TypeError, + "Callback needs to be a function or method not %s", + py_arg->ob_type->tp_name); + + return FALSE; + } + + callable_info = (GICallableInfo *)callback_cache->interface_info; + + closure = _pygi_make_native_closure (callable_info, callback_cache->scope, py_arg, py_user_data); + arg->v_pointer = closure->closure; + + /* always decref the user data as _pygi_make_native_closure adds its own ref */ + Py_XDECREF (py_user_data); + + /* The PyGICClosure instance is used as user data passed into the C function. + * The return trip to python will marshal this back and pull the python user data out. + */ + if (user_data_cache != NULL) { + state->in_args[user_data_cache->c_arg_index].v_pointer = closure; + } + + /* Setup a GDestroyNotify callback if this method supports it along with + * a user data field. The user data field is a requirement in order + * free resources and ref counts associated with this arguments closure. + * In case a user data field is not available, show a warning giving + * explicit information and setup a dummy notification to avoid a crash + * later on in _pygi_destroy_notify_callback_closure. + */ + if (callback_cache->destroy_notify_index > 0) { + destroy_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->destroy_notify_index); + } + + if (destroy_cache) { + if (user_data_cache != NULL) { + PyGICClosure *destroy_notify = _pygi_destroy_notify_create (); + state->in_args[destroy_cache->c_arg_index].v_pointer = destroy_notify->closure; + } else { + gchar *msg = g_strdup_printf("Callables passed to %s will leak references because " + "the method does not support a user_data argument. " + "See: https://bugzilla.gnome.org/show_bug.cgi?id=685598", + callable_cache->name); + if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 2)) { + g_free(msg); + _pygi_invoke_closure_free(closure); + return FALSE; + } + g_free(msg); + state->in_args[destroy_cache->c_arg_index].v_pointer = _pygi_destroy_notify_dummy; + } + } + + /* Use the PyGIClosure as data passed to cleanup for GI_SCOPE_TYPE_CALL. */ + *cleanup_data = closure; + + return TRUE; +} + +static PyObject * +_pygi_marshal_to_py_interface_callback (PyGIInvokeState *state, + PyGICallableCache *callable_cache, + PyGIArgCache *arg_cache, + GIArgument *arg) +{ + PyObject *py_obj = NULL; + + PyErr_Format (PyExc_NotImplementedError, + "Marshalling a callback to PyObject is not supported"); + return py_obj; +} + +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); + } +} + +static void +_pygi_marshal_cleanup_from_py_interface_callback (PyGIInvokeState *state, + PyGIArgCache *arg_cache, + PyObject *py_arg, + gpointer data, + gboolean was_processed) +{ + PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache; + if (was_processed && callback_cache->scope == GI_SCOPE_TYPE_CALL) { + _pygi_invoke_closure_free (data); + } +} + +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; + user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */ + _pygi_callable_cache_set_arg (callable_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; + _pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index, + destroy_arg_cache); + } + arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback; + arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback; +} + + +static gboolean +pygi_arg_callback_setup_from_info (PyGICallbackCache *arg_cache, + GITypeInfo *type_info, + GIArgInfo *arg_info, /* may be null */ + GITransfer transfer, + PyGIDirection direction, + GIInterfaceInfo *iface_info, + PyGICallableCache *callable_cache) +{ + gssize child_offset = 0; + + if (!pygi_arg_base_setup ((PyGIArgCache *)arg_cache, + type_info, + arg_info, + transfer, + direction)) { + return FALSE; + } + + if (direction & PYGI_DIRECTION_TO_PYTHON) { + ((PyGIArgCache *)arg_cache)->to_py_marshaller = _pygi_marshal_to_py_interface_callback; + } + + if (callable_cache != NULL) + child_offset = + (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD || + callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0; + + ( (PyGIArgCache *)arg_cache)->destroy_notify = (GDestroyNotify)_callback_cache_free_func; + + arg_cache->user_data_index = g_arg_info_get_closure (arg_info); + if (arg_cache->user_data_index != -1) + arg_cache->user_data_index += child_offset; + arg_cache->destroy_notify_index = g_arg_info_get_destroy (arg_info); + if (arg_cache->destroy_notify_index != -1) + arg_cache->destroy_notify_index += child_offset; + arg_cache->scope = g_arg_info_get_scope (arg_info); + g_base_info_ref( (GIBaseInfo *)iface_info); + arg_cache->interface_info = iface_info; + + if (direction & PYGI_DIRECTION_FROM_PYTHON) + _arg_cache_from_py_interface_callback_setup ((PyGIArgCache *)arg_cache, callable_cache); + + return TRUE; +} + +PyGIArgCache * +pygi_arg_callback_new_from_info (GITypeInfo *type_info, + GIArgInfo *arg_info, /* may be null */ + GITransfer transfer, + PyGIDirection direction, + GIInterfaceInfo *iface_info, + PyGICallableCache *callable_cache) +{ + gboolean res = FALSE; + PyGICallbackCache *callback_cache; + + callback_cache = g_slice_new0 (PyGICallbackCache); + if (callback_cache == NULL) + return NULL; + + res = pygi_arg_callback_setup_from_info (callback_cache, + type_info, + arg_info, + transfer, + direction, + iface_info, + callable_cache); + if (res) { + return (PyGIArgCache *)callback_cache; + } else { + _pygi_arg_cache_free ((PyGIArgCache *)callback_cache); + return NULL; + } +} diff --git a/gi/pygi-closure.h b/gi/pygi-closure.h index 6f983398..0620dc7e 100644 --- a/gi/pygi-closure.h +++ b/gi/pygi-closure.h @@ -12,9 +12,7 @@ * 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 + * License along with this library; if not, see . */ #ifndef __PYGI_CLOSURE_H__ @@ -24,6 +22,8 @@ #include #include +#include "pygi-cache.h" + G_BEGIN_DECLS @@ -52,6 +52,13 @@ PyGICClosure* _pygi_make_native_closure (GICallableInfo* info, PyObject *function, gpointer user_data); +PyGIArgCache *pygi_arg_callback_new_from_info (GITypeInfo *type_info, + GIArgInfo *arg_info, /* may be null */ + GITransfer transfer, + PyGIDirection direction, + GIInterfaceInfo *iface_info, + PyGICallableCache *callable_cache); + G_END_DECLS #endif /* __PYGI_CLOSURE_H__ */ diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c index a8fa3f67..0376e37b 100644 --- a/gi/pygi-marshal-cleanup.c +++ b/gi/pygi-marshal-cleanup.c @@ -233,20 +233,6 @@ _pygi_marshal_cleanup_to_py_interface_object (PyGIInvokeState *state, g_object_unref (G_OBJECT(data)); } - -void -_pygi_marshal_cleanup_from_py_interface_callback (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *py_arg, - gpointer data, - gboolean was_processed) -{ - PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache; - if (was_processed && callback_cache->scope == GI_SCOPE_TYPE_CALL) { - _pygi_invoke_closure_free (data); - } -} - void _pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state, PyGIArgCache *arg_cache, diff --git a/gi/pygi-marshal-cleanup.h b/gi/pygi-marshal-cleanup.h index eaacb8db..530f5f31 100644 --- a/gi/pygi-marshal-cleanup.h +++ b/gi/pygi-marshal-cleanup.h @@ -65,11 +65,6 @@ void _pygi_marshal_cleanup_to_py_interface_object (PyGIInvokeState *stat PyObject *dummy, gpointer data, gboolean was_processed); -void _pygi_marshal_cleanup_from_py_interface_callback (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *py_arg, - gpointer data, - gboolean was_processed); G_END_DECLS #endif /* __PYGI_MARSHAL_CLEANUP_H__ */ diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c index c6fe1c21..92c89c84 100644 --- a/gi/pygi-marshal-from-py.c +++ b/gi/pygi-marshal-from-py.c @@ -140,166 +140,6 @@ _is_union_member (GIInterfaceInfo *interface_info, PyObject *py_arg) { return is_member; } -/* _pygi_destroy_notify_dummy: - * - * Dummy method used in the occasion when a method has a GDestroyNotify - * argument without user data. - */ -static void -_pygi_destroy_notify_dummy (gpointer data) { -} - -static PyGICClosure *global_destroy_notify; - -static void -_pygi_destroy_notify_callback_closure (ffi_cif *cif, - void *result, - void **args, - void *data) -{ - PyGICClosure *info = * (void**) (args[0]); - - g_assert (info); - - _pygi_invoke_closure_free (info); -} - -/* _pygi_destroy_notify_create: - * - * Method used in the occasion when a method has a GDestroyNotify - * argument with user data. - */ -static PyGICClosure* -_pygi_destroy_notify_create (void) -{ - if (!global_destroy_notify) { - - PyGICClosure *destroy_notify = g_slice_new0 (PyGICClosure); - GIBaseInfo* glib_destroy_notify; - - g_assert (destroy_notify); - - glib_destroy_notify = g_irepository_find_by_name (NULL, "GLib", "DestroyNotify"); - g_assert (glib_destroy_notify != NULL); - g_assert (g_base_info_get_type (glib_destroy_notify) == GI_INFO_TYPE_CALLBACK); - - destroy_notify->closure = g_callable_info_prepare_closure ( (GICallableInfo*) glib_destroy_notify, - &destroy_notify->cif, - _pygi_destroy_notify_callback_closure, - NULL); - - global_destroy_notify = destroy_notify; - } - - return global_destroy_notify; -} - -gboolean -_pygi_marshal_from_py_interface_callback (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - PyObject *py_arg, - GIArgument *arg, - gpointer *cleanup_data) -{ - GICallableInfo *callable_info; - PyGICClosure *closure; - PyGIArgCache *user_data_cache = NULL; - PyGIArgCache *destroy_cache = NULL; - PyGICallbackCache *callback_cache; - PyObject *py_user_data = NULL; - - callback_cache = (PyGICallbackCache *)arg_cache; - - if (callback_cache->user_data_index > 0) { - user_data_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->user_data_index); - if (user_data_cache->py_arg_index < state->n_py_in_args) { - /* py_user_data is a borrowed reference. */ - py_user_data = PyTuple_GetItem (state->py_in_args, user_data_cache->py_arg_index); - if (!py_user_data) - return FALSE; - /* NULL out user_data if it was not supplied and the default arg placeholder - * was used instead. - */ - if (py_user_data == _PyGIDefaultArgPlaceholder) { - py_user_data = NULL; - } else if (callable_cache->user_data_varargs_index < 0) { - /* For non-variable length user data, place the user data in a - * single item tuple which is concatenated to the callbacks arguments. - * This allows callback input arg marshaling to always expect a - * tuple for user data. Note the - */ - py_user_data = Py_BuildValue("(O)", py_user_data, NULL); - } else { - /* increment the ref borrowed from PyTuple_GetItem above */ - Py_INCREF (py_user_data); - } - } - } - - if (py_arg == Py_None) { - return TRUE; - } - - if (!PyCallable_Check (py_arg)) { - PyErr_Format (PyExc_TypeError, - "Callback needs to be a function or method not %s", - py_arg->ob_type->tp_name); - - return FALSE; - } - - callable_info = (GICallableInfo *)callback_cache->interface_info; - - closure = _pygi_make_native_closure (callable_info, callback_cache->scope, py_arg, py_user_data); - arg->v_pointer = closure->closure; - - /* always decref the user data as _pygi_make_native_closure adds its own ref */ - Py_XDECREF (py_user_data); - - /* The PyGICClosure instance is used as user data passed into the C function. - * The return trip to python will marshal this back and pull the python user data out. - */ - if (user_data_cache != NULL) { - state->in_args[user_data_cache->c_arg_index].v_pointer = closure; - } - - /* Setup a GDestroyNotify callback if this method supports it along with - * a user data field. The user data field is a requirement in order - * free resources and ref counts associated with this arguments closure. - * In case a user data field is not available, show a warning giving - * explicit information and setup a dummy notification to avoid a crash - * later on in _pygi_destroy_notify_callback_closure. - */ - if (callback_cache->destroy_notify_index > 0) { - destroy_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->destroy_notify_index); - } - - if (destroy_cache) { - if (user_data_cache != NULL) { - PyGICClosure *destroy_notify = _pygi_destroy_notify_create (); - state->in_args[destroy_cache->c_arg_index].v_pointer = destroy_notify->closure; - } else { - gchar *msg = g_strdup_printf("Callables passed to %s will leak references because " - "the method does not support a user_data argument. " - "See: https://bugzilla.gnome.org/show_bug.cgi?id=685598", - callable_cache->name); - if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 2)) { - g_free(msg); - _pygi_invoke_closure_free(closure); - return FALSE; - } - g_free(msg); - state->in_args[destroy_cache->c_arg_index].v_pointer = _pygi_destroy_notify_dummy; - } - } - - /* Use the PyGIClosure as data passed to cleanup for GI_SCOPE_TYPE_CALL. */ - *cleanup_data = closure; - - return TRUE; -} - gboolean _pygi_marshal_from_py_interface_enum (PyGIInvokeState *state, PyGICallableCache *callable_cache, diff --git a/gi/pygi-marshal-from-py.h b/gi/pygi-marshal-from-py.h index a49c179e..0172c197 100644 --- a/gi/pygi-marshal-from-py.h +++ b/gi/pygi-marshal-from-py.h @@ -33,12 +33,6 @@ G_BEGIN_DECLS gboolean _pygi_marshal_from_py_ssize_t (PyGIArgCache *arg_cache, Py_ssize_t size, GIArgument *arg); -gboolean _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - PyObject *py_arg, - GIArgument *arg, - gpointer *cleanup_data); gboolean _pygi_marshal_from_py_interface_enum (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c index e890b1ee..69a7c1ae 100644 --- a/gi/pygi-marshal-to-py.c +++ b/gi/pygi-marshal-to-py.c @@ -74,19 +74,6 @@ gi_argument_to_c_long (GIArgument *arg_in, } } -PyObject * -_pygi_marshal_to_py_interface_callback (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - GIArgument *arg) -{ - PyObject *py_obj = NULL; - - PyErr_Format (PyExc_NotImplementedError, - "Marshalling a callback to PyObject is not supported"); - return py_obj; -} - PyObject * _pygi_marshal_to_py_interface_enum (PyGIInvokeState *state, PyGICallableCache *callable_cache, diff --git a/gi/pygi-marshal-to-py.h b/gi/pygi-marshal-to-py.h index edf19892..de8f85b7 100644 --- a/gi/pygi-marshal-to-py.h +++ b/gi/pygi-marshal-to-py.h @@ -22,10 +22,6 @@ #ifndef __PYGI_MARSHAL_TO_PY_H__ #define __PYGI_MARSHAL_TO_PY_H__ -PyObject *_pygi_marshal_to_py_interface_callback(PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - GIArgument *arg); PyObject *_pygi_marshal_to_py_interface_enum (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, -- cgit v1.2.1