[pygobject] Add cleanup_data argument used for Python to C marshaler cleanup
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Add cleanup_data argument used for Python to C marshaler cleanup
- Date: Mon, 14 Oct 2013 22:10:03 +0000 (UTC)
commit 7407367f424595c2780a2d6a47d936ad0bd91735
Author: Simon Feltman <sfeltman src gnome org>
Date: Mon Oct 7 14:11:39 2013 -0700
Add cleanup_data argument used for Python to C marshaler cleanup
Add a new output argument to all from_py marshalers which is used for
keeping track of marshaling data that later needs cleanup. Previously most
marshalers would rely on the GIArgument->v_pointer as the means for data
cleanup. However, this pointer would get clobbered in the case of
bi-directional arguments (inout) and the memory lost.
Use the new cleanup_data for storing temporarily wrapped C arrays so we
don't need to re-calculate the length argument during cleanup.
Additionally delay the from_py marshaling cleanup function until after
_invoke_marshal_out_args is called. This gives inout arguments which don't
modify the pointer sufficient time to exist until they marshaled back to
Python (gi_marshalling_tests_gvalue_inout).
https://bugzilla.gnome.org/show_bug.cgi?id=693402
gi/pygi-argument.c | 4 +-
gi/pygi-cache.h | 3 +-
gi/pygi-invoke-state-struct.h | 7 +-
gi/pygi-invoke.c | 20 +++--
gi/pygi-marshal-cleanup.c | 43 +++++-------
gi/pygi-marshal-from-py.c | 160 +++++++++++++++++++++++++++-------------
gi/pygi-marshal-from-py.h | 45 ++++++++----
7 files changed, 177 insertions(+), 105 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 3b857be..6378892 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -894,11 +894,13 @@ _pygi_argument_from_object (PyObject *object,
{
GIArgument arg;
GITypeTag type_tag;
+ gpointer cleanup_data = NULL;
memset(&arg, 0, sizeof(GIArgument));
type_tag = g_type_info_get_tag (type_info);
- if (_pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer) ||
+ /* Ignores cleanup data for now. */
+ if (_pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer, &cleanup_data) ||
PyErr_Occurred()) {
return arg;
}
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 1b32381..745d0a1 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -36,7 +36,8 @@ typedef gboolean (*PyGIMarshalFromPyFunc) (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
typedef PyObject *(*PyGIMarshalToPyFunc) (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
diff --git a/gi/pygi-invoke-state-struct.h b/gi/pygi-invoke-state-struct.h
index 1d9e49c..139b878 100644
--- a/gi/pygi-invoke-state-struct.h
+++ b/gi/pygi-invoke-state-struct.h
@@ -18,9 +18,10 @@ typedef struct _PyGIInvokeState
GIArgument **args;
GIArgument *in_args;
- /* Generic array allocated to the same length as args
- * for use as extra per-arg state data. */
- gpointer *args_data;
+ /* Array of pointers allocated to the same length as args which holds from_py
+ * marshaler cleanup data.
+ */
+ gpointer *args_cleanup_data;
/* Out args and out values
* In order to pass a parameter and get something back out in C
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 9dc40d6..675b0ef 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -350,8 +350,8 @@ _invoke_state_init_from_callable_cache (PyGIInvokeState *state,
return FALSE;
}
- state->args_data = g_slice_alloc0 (_pygi_callable_cache_args_len (cache) * sizeof (gpointer));
- if (state->args_data == NULL && _pygi_callable_cache_args_len (cache) != 0) {
+ state->args_cleanup_data = g_slice_alloc0 (_pygi_callable_cache_args_len (cache) * sizeof (gpointer));
+ if (state->args_cleanup_data == NULL && _pygi_callable_cache_args_len (cache) != 0) {
PyErr_NoMemory();
return FALSE;
}
@@ -383,7 +383,7 @@ static inline void
_invoke_state_clear (PyGIInvokeState *state, PyGICallableCache *cache)
{
g_slice_free1 (_pygi_callable_cache_args_len (cache) * sizeof(GIArgument *), state->args);
- g_slice_free1 (_pygi_callable_cache_args_len (cache) * sizeof(gpointer), state->args_data);
+ g_slice_free1 (_pygi_callable_cache_args_len (cache) * sizeof(gpointer), state->args_cleanup_data);
g_slice_free1 (cache->n_from_py_args * sizeof(GIArgument), state->in_args);
g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_args);
g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_values);
@@ -539,6 +539,8 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
*c_arg = arg_cache->default_value;
} else if (arg_cache->from_py_marshaller != NULL) {
gboolean success;
+ gpointer cleanup_data = NULL;
+
if (!arg_cache->allow_none && py_arg == Py_None) {
PyErr_Format (PyExc_TypeError,
"Argument %zd does not allow None as a value",
@@ -550,10 +552,12 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
return FALSE;
}
success = arg_cache->from_py_marshaller (state,
- cache,
- arg_cache,
- py_arg,
- c_arg);
+ cache,
+ arg_cache,
+ py_arg,
+ c_arg,
+ &cleanup_data);
+ state->args_cleanup_data[i] = cleanup_data;
if (!success) {
pygi_marshal_cleanup_args_from_py_parameter_fail (state,
@@ -701,9 +705,9 @@ pygi_callable_info_invoke (GIBaseInfo *info, PyObject *py_args,
if (!_invoke_callable (&state, cache, info, function_ptr))
goto err;
+ ret = _invoke_marshal_out_args (&state, cache);
pygi_marshal_cleanup_args_from_py_marshal_success (&state, cache);
- ret = _invoke_marshal_out_args (&state, cache);
if (ret)
pygi_marshal_cleanup_args_to_py_marshal_success (&state, cache);
err:
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
index cd059a4..29ea617 100644
--- a/gi/pygi-marshal-cleanup.c
+++ b/gi/pygi-marshal-cleanup.c
@@ -94,23 +94,23 @@ pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState *state,
{
gssize i;
- /* For in success, call cleanup for all GI_DIRECTION_IN values only. */
for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
PyObject *py_arg = PyTuple_GET_ITEM (state->py_in_args,
arg_cache->py_arg_index);
+ gpointer cleanup_data = state->args_cleanup_data[i];
- if (cleanup_func &&
- arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON &&
- state->args[i]->v_pointer != NULL)
- cleanup_func (state, arg_cache, py_arg, state->args[i]->v_pointer, TRUE);
-
- if (cleanup_func &&
- arg_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL &&
- state->args_data[i] != NULL) {
- cleanup_func (state, arg_cache, py_arg, state->args_data[i], TRUE);
- state->args_data[i] = NULL;
+ /* Only cleanup using args_cleanup_data when available.
+ * It is the responsibility of the various "from_py" marshalers to return
+ * cleanup_data which is then passed into their respective cleanup function.
+ * PyGIInvokeState.args_cleanup_data stores this data (via _invoke_marshal_in_args)
+ * for the duration of the invoke up until this point.
+ */
+ if (cleanup_func && cleanup_data != NULL &&
+ arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
+ cleanup_func (state, arg_cache, py_arg, cleanup_data, TRUE);
+ state->args_cleanup_data[i] = NULL;
}
}
}
@@ -213,9 +213,8 @@ _pygi_marshal_cleanup_from_py_utf8 (PyGIInvokeState *state,
gpointer data,
gboolean was_processed)
{
- /* We strdup strings so always free if we have processed this
- parameter for input */
- if (was_processed)
+ /* We strdup strings so free unless ownership is transferred to C. */
+ if (was_processed && arg_cache->transfer == GI_TRANSFER_NOTHING)
g_free (data);
}
@@ -270,8 +269,7 @@ _pygi_marshal_cleanup_from_py_interface_callback (PyGIInvokeState *state,
{
PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
if (was_processed && callback_cache->scope == GI_SCOPE_TYPE_CALL) {
- _pygi_invoke_closure_free (state->args_data[arg_cache->c_arg_index]);
- state->args_data[arg_cache->c_arg_index] = NULL;
+ _pygi_invoke_closure_free (data);
}
}
@@ -366,15 +364,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
GPtrArray *ptr_array_ = NULL;
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
- /* If this isn't a garray create one to help process variable sized
- array elements */
- if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
- array_ = _wrap_c_array (state, sequence_cache, data);
-
- if (array_ == NULL)
- return;
-
- } else if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
ptr_array_ = (GPtrArray *) data;
} else {
array_ = (GArray *) data;
@@ -418,6 +408,9 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
/* Only free the array when we didn't transfer ownership */
if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
+ /* always free the GArray wrapper created in from_py marshaling and
+ * passed back as cleanup_data
+ */
g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING);
} else if (state->failed ||
arg_cache->transfer == GI_TRANSFER_NOTHING) {
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index df22863..a2b58cc 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -247,7 +247,8 @@ _pygi_marshal_from_py_void (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
g_warn_if_fail (arg_cache->transfer == GI_TRANSFER_NOTHING);
@@ -264,6 +265,7 @@ _pygi_marshal_from_py_void (PyGIInvokeState *state,
return FALSE;
}
+ *cleanup_data = arg->v_pointer;
return TRUE;
}
@@ -408,7 +410,8 @@ _pygi_marshal_from_py_gtype (PyObject *py_arg,
static gboolean
_pygi_marshal_from_py_utf8 (PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
gchar *string_;
@@ -437,12 +440,14 @@ _pygi_marshal_from_py_utf8 (PyObject *py_arg,
}
arg->v_string = string_;
+ *cleanup_data = arg->v_string;
return TRUE;
}
static gboolean
_pygi_marshal_from_py_filename (PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
gchar *string_;
GError *error = NULL;
@@ -476,6 +481,7 @@ _pygi_marshal_from_py_filename (PyObject *py_arg,
return FALSE;
}
+ *cleanup_data = arg->v_string;
return TRUE;
}
@@ -626,7 +632,8 @@ gboolean
_pygi_marshal_from_py_basic_type (PyObject *object, /* in */
GIArgument *arg, /* out */
GITypeTag type_tag,
- GITransfer transfer)
+ GITransfer transfer,
+ gpointer *cleanup_data /* out */)
{
switch (type_tag) {
case GI_TYPE_TAG_VOID:
@@ -639,6 +646,7 @@ _pygi_marshal_from_py_basic_type (PyObject *object, /* in */
"See: https://bugzilla.gnome.org/show_bug.cgi?id=683599");
} else {
arg->v_pointer = PyLong_AsVoidPtr (object);
+ *cleanup_data = arg->v_pointer;
}
break;
case GI_TYPE_TAG_INT8:
@@ -682,10 +690,10 @@ _pygi_marshal_from_py_basic_type (PyObject *object, /* in */
return _pygi_marshal_from_py_unichar (object, arg);
case GI_TYPE_TAG_UTF8:
- return _pygi_marshal_from_py_utf8 (object, arg);
+ return _pygi_marshal_from_py_utf8 (object, arg, cleanup_data);
case GI_TYPE_TAG_FILENAME:
- return _pygi_marshal_from_py_filename (object, arg);
+ return _pygi_marshal_from_py_filename (object, arg, cleanup_data);
default:
return FALSE;
@@ -702,12 +710,14 @@ _pygi_marshal_from_py_basic_type_cache_adapter (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
return _pygi_marshal_from_py_basic_type (py_arg,
arg,
arg_cache->type_tag,
- arg_cache->transfer);
+ arg_cache->transfer,
+ cleanup_data);
}
gboolean
@@ -715,7 +725,8 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyGIMarshalFromPyFunc from_py_marshaller;
int i = 0;
@@ -781,6 +792,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
for (i = 0, success_count = 0; i < length; i++) {
GIArgument item = {0};
+ gpointer item_cleanup_data = NULL;
PyObject *py_item = PySequence_GetItem (py_arg, i);
if (py_item == NULL)
goto err;
@@ -789,12 +801,27 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
callable_cache,
sequence_cache->item_cache,
py_item,
- &item)) {
+ &item,
+ &item_cleanup_data)) {
Py_DECREF (py_item);
goto err;
}
-
Py_DECREF (py_item);
+
+ if (item_cleanup_data != NULL && item_cleanup_data != item.v_pointer) {
+ /* We only support one level of data discrepancy between an items
+ * data and its cleanup data. This is because we only track a single
+ * extra cleanup data pointer per-argument and cannot track the entire
+ * array of items differing data and cleanup_data.
+ * For example, this would fail if trying to marshal an array of
+ * callback closures marked with SCOPE call type where the cleanup data
+ * is different from the items v_pointer, likewise an array of arrays.
+ */
+ PyErr_SetString(PyExc_RuntimeError, "Cannot cleanup item data for array due to "
+ "the items data its cleanup data being different.");
+ goto err;
+ }
+
/* FIXME: it is much more efficent to have seperate marshaller
* for ptr arrays than doing the evaluation
* and casting each loop iteration
@@ -826,6 +853,8 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
g_value_copy ((GValue*) item.v_pointer, dest);
}
+ /* Manually increment the length because we are manually setting the memory. */
+ array_->len++;
} else {
/* Handles flat arrays of boxed or struct types. */
@@ -837,7 +866,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
* due to "item" being a temporarily marshaled value done on the stack.
*/
if (from_py_cleanup)
- from_py_cleanup (state, item_arg_cache, py_item, item.v_pointer, TRUE);
+ from_py_cleanup (state, item_arg_cache, py_item, item_cleanup_data, TRUE);
break;
}
@@ -910,19 +939,16 @@ array_success:
if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
arg->v_pointer = array_->data;
- g_array_free (array_, FALSE);
} else {
arg->v_pointer = array_;
}
- /* Store the allocated array in the arguments extra data for bi-directional
- * marshaling cleanup. This is needed because arg->v_pointer will be
- * clobbered by the caller and we would have no way to clean it up later.
- * TODO: This should go in the outer layer and apply generically at some point.
+ /* In all cases give the array object back as cleanup data.
+ * In the case of GI_ARRAY_C, we give the data directly as the argument
+ * but keep the array_ wrapper as cleanup data so we don't have to find
+ * it's length again.
*/
- if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
- state->args_data[arg_cache->c_arg_index] = arg->v_pointer;
- }
+ *cleanup_data = array_;
return TRUE;
}
@@ -932,7 +958,8 @@ _pygi_marshal_from_py_glist (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyGIMarshalFromPyFunc from_py_marshaller;
int i;
@@ -966,7 +993,8 @@ _pygi_marshal_from_py_glist (PyGIInvokeState *state,
from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
for (i = 0; i < length; i++) {
- GIArgument item;
+ GIArgument item = {0};
+ gpointer item_cleanup_data = NULL;
PyObject *py_item = PySequence_GetItem (py_arg, i);
if (py_item == NULL)
goto err;
@@ -975,7 +1003,8 @@ _pygi_marshal_from_py_glist (PyGIInvokeState *state,
callable_cache,
sequence_cache->item_cache,
py_item,
- &item))
+ &item,
+ &item_cleanup_data))
goto err;
Py_DECREF (py_item);
@@ -994,6 +1023,7 @@ err:
}
arg->v_pointer = g_list_reverse (list_);
+ *cleanup_data = arg->v_pointer;
return TRUE;
}
@@ -1002,7 +1032,8 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyGIMarshalFromPyFunc from_py_marshaller;
int i;
@@ -1035,7 +1066,8 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState *state,
from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
for (i = 0; i < length; i++) {
- GIArgument item;
+ GIArgument item = {0};
+ gpointer item_cleanup_data = NULL;
PyObject *py_item = PySequence_GetItem (py_arg, i);
if (py_item == NULL)
goto err;
@@ -1044,7 +1076,8 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState *state,
callable_cache,
sequence_cache->item_cache,
py_item,
- &item))
+ &item,
+ &item_cleanup_data))
goto err;
Py_DECREF (py_item);
@@ -1064,6 +1097,7 @@ err:
}
arg->v_pointer = g_slist_reverse (list_);
+ *cleanup_data = arg->v_pointer;
return TRUE;
}
@@ -1072,7 +1106,8 @@ _pygi_marshal_from_py_ghash (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyGIMarshalFromPyFunc key_from_py_marshaller;
PyGIMarshalFromPyFunc value_from_py_marshaller;
@@ -1135,6 +1170,8 @@ _pygi_marshal_from_py_ghash (PyGIInvokeState *state,
for (i = 0; i < length; i++) {
GIArgument key, value;
+ gpointer key_cleanup_data = NULL;
+ gpointer value_cleanup_data = NULL;
PyObject *py_key = PyList_GET_ITEM (py_keys, i);
PyObject *py_value = PyList_GET_ITEM (py_values, i);
if (py_key == NULL || py_value == NULL)
@@ -1144,14 +1181,16 @@ _pygi_marshal_from_py_ghash (PyGIInvokeState *state,
callable_cache,
hash_cache->key_cache,
py_key,
- &key))
+ &key,
+ &key_cleanup_data))
goto err;
if (!value_from_py_marshaller ( state,
callable_cache,
hash_cache->value_cache,
py_value,
- &value))
+ &value,
+ &value_cleanup_data))
goto err;
g_hash_table_insert (hash_,
@@ -1170,6 +1209,7 @@ err:
}
arg->v_pointer = hash_;
+ *cleanup_data = arg->v_pointer;
return TRUE;
}
@@ -1178,7 +1218,8 @@ _pygi_marshal_from_py_gerror (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyErr_Format (PyExc_NotImplementedError,
"Marshalling for GErrors is not implemented");
@@ -1244,7 +1285,8 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
GICallableInfo *callable_info;
PyGICClosure *closure;
@@ -1331,10 +1373,8 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
}
}
- /* Store the PyGIClosure as extra args data so _pygi_marshal_cleanup_from_py_interface_callback
- * can clean it up later for GI_SCOPE_TYPE_CALL based closures.
- */
- state->args_data[arg_cache->c_arg_index] = closure;
+ /* Use the PyGIClosure as data passed to cleanup for GI_SCOPE_TYPE_CALL. */
+ *cleanup_data = closure;
return TRUE;
}
@@ -1344,7 +1384,8 @@ _pygi_marshal_from_py_interface_enum (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyObject *py_long;
long c_long;
@@ -1412,7 +1453,8 @@ _pygi_marshal_from_py_interface_flags (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyObject *py_long;
long c_long;
@@ -1459,20 +1501,27 @@ _pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
- return _pygi_marshal_from_py_interface_struct (py_arg,
- arg,
- arg_cache->arg_name,
- iface_cache->interface_info,
- iface_cache->g_type,
- iface_cache->py_type,
- arg_cache->transfer,
- TRUE, /*copy_reference*/
- iface_cache->is_foreign,
- arg_cache->is_pointer);
+ gboolean res = _pygi_marshal_from_py_interface_struct (py_arg,
+ arg,
+ arg_cache->arg_name,
+ iface_cache->interface_info,
+ iface_cache->g_type,
+ iface_cache->py_type,
+ arg_cache->transfer,
+ TRUE, /*copy_reference*/
+ iface_cache->is_foreign,
+ arg_cache->is_pointer);
+
+ /* Assume struct marshaling is always a pointer and assign cleanup_data
+ * here rather than passing it further down the chain.
+ */
+ *cleanup_data = arg->v_pointer;
+ return res;
}
gboolean
@@ -1480,7 +1529,8 @@ _pygi_marshal_from_py_interface_boxed (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyErr_Format (PyExc_NotImplementedError,
"Marshalling for this type is not implemented yet");
@@ -1492,8 +1542,11 @@ _pygi_marshal_from_py_interface_object (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
+ gboolean res = FALSE;
+
if (py_arg == Py_None) {
arg->v_pointer = NULL;
return TRUE;
@@ -1513,7 +1566,9 @@ _pygi_marshal_from_py_interface_object (PyGIInvokeState *state,
return FALSE;
}
- return _pygi_marshal_from_py_gobject (py_arg, arg, arg_cache->transfer);
+ res = _pygi_marshal_from_py_gobject (py_arg, arg, arg_cache->transfer);
+ *cleanup_data = arg->v_pointer;
+ return res;
}
gboolean
@@ -1521,7 +1576,8 @@ _pygi_marshal_from_py_interface_union (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyErr_Format(PyExc_NotImplementedError,
"Marshalling for this type is not implemented yet");
diff --git a/gi/pygi-marshal-from-py.h b/gi/pygi-marshal-from-py.h
index e8b9031..f8e4699 100644
--- a/gi/pygi-marshal-from-py.h
+++ b/gi/pygi-marshal-from-py.h
@@ -37,78 +37,93 @@ gboolean _pygi_marshal_from_py_void (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_array (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_glist (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_gslist (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_ghash (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_gerror (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_interface_callback (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_interface_enum (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_interface_flags (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_interface_boxed (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_interface_object (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_interface_union (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
/* Simplified marshalers shared between vfunc/closure and direct function calls. */
gboolean _pygi_marshal_from_py_basic_type (PyObject *object, /* in */
GIArgument *arg, /* out */
GITypeTag type_tag,
- GITransfer transfer);
+ GITransfer transfer,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_basic_type_cache_adapter (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
gboolean _pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
GIArgument *arg, /*out*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]