[pygobject] cache refactoring: Move closure setup and marshaling into pygi-closure
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] cache refactoring: Move closure setup and marshaling into pygi-closure
- Date: Mon, 3 Feb 2014 13:55:45 +0000 (UTC)
commit 2cddba811592fbb990322fbf2dce516ffd7e94cd
Author: Simon Feltman <sfeltman src gnome org>
Date: Sat Oct 12 12:39:20 2013 -0700
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 d91d8ab..aded025 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)
{
@@ -335,38 +303,6 @@ _arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
}
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 0629646..d20cb9f 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 5df4713..3dd73da 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 <http://www.gnu.org/licenses/>.
*/
#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 6f98339..0620dc7 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __PYGI_CLOSURE_H__
@@ -24,6 +22,8 @@
#include <girffi.h>
#include <ffi.h>
+#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 a8fa3f6..0376e37 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 eaacb8d..530f5f3 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 c6fe1c2..92c89c8 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 a49c179..0172c19 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 e890b1e..69a7c1a 100644
--- a/gi/pygi-marshal-to-py.c
+++ b/gi/pygi-marshal-to-py.c
@@ -75,19 +75,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,
PyGIArgCache *arg_cache,
diff --git a/gi/pygi-marshal-to-py.h b/gi/pygi-marshal-to-py.h
index edf1989..de8f85b 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,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]