summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gi/pygi-cache.c160
-rw-r--r--gi/pygi-cache.h16
-rw-r--r--gi/pygi-invoke.c4
-rw-r--r--gi/pygi-marshal-cleanup.c28
-rw-r--r--gi/pygi-marshal-from-py.c37
-rw-r--r--gi/pygi-marshal-to-py.c23
6 files changed, 177 insertions, 91 deletions
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 9793ffee..a8468cce 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -160,6 +160,15 @@ _sequence_cache_free_func (PyGISequenceCache *cache)
}
static void
+_array_cache_free_func (PyGIArgGArray *cache)
+{
+ if (cache != NULL) {
+ _pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache);
+ g_slice_free (PyGIArgGArray, cache);
+ }
+}
+
+static void
_callback_cache_free_func (PyGICallbackCache *cache)
{
if (cache != NULL) {
@@ -206,27 +215,26 @@ _interface_cache_new (GIInterfaceInfo *iface_info)
return ic;
}
-static PyGISequenceCache *
-_sequence_cache_new (GITypeInfo *type_info,
- GIDirection direction,
- GITransfer transfer,
- gssize child_offset)
+gboolean
+pygi_arg_sequence_setup (PyGISequenceCache *sc,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction)
{
- PyGISequenceCache *sc;
GITypeInfo *item_type_info;
GITransfer item_transfer;
- sc = g_slice_new0 (PyGISequenceCache);
- ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
-
- sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
- sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
- sc->len_arg_index = g_type_info_get_array_length (type_info);
- if (sc->len_arg_index >= 0)
- sc->len_arg_index += child_offset;
+ if (!pygi_arg_base_setup ((PyGIArgCache *)sc,
+ type_info,
+ arg_info,
+ transfer,
+ direction)) {
+ return FALSE;
+ }
+ 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;
@@ -237,17 +245,89 @@ _sequence_cache_new (GITypeInfo *type_info,
0, 0,
NULL);
+ g_base_info_unref ( (GIBaseInfo *)item_type_info);
+
if (sc->item_cache == NULL) {
- _pygi_arg_cache_free ( (PyGIArgCache *)sc);
- return NULL;
+ return FALSE;
}
+ return TRUE;
+}
+
+static gboolean
+pygi_arg_garray_setup (PyGIArgGArray *sc,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction,
+ gssize child_offset)
+{
+ GITypeInfo *item_type_info;
+
+ if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc,
+ type_info,
+ arg_info,
+ transfer,
+ direction)) {
+ return FALSE;
+ }
+
+ ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func;
+ sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
+ sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
+ sc->len_arg_index = g_type_info_get_array_length (type_info);
+ if (sc->len_arg_index >= 0)
+ sc->len_arg_index += child_offset;
+
+ item_type_info = g_type_info_get_param_type (type_info, 0);
sc->item_size = _pygi_g_type_info_size (item_type_info);
g_base_info_unref ( (GIBaseInfo *)item_type_info);
+ return TRUE;
+}
+
+static PyGISequenceCache *
+pygi_arg_sequence_new (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ PyGISequenceCache *sc = g_slice_new0 (PyGISequenceCache);
+ if (sc == NULL)
+ return NULL;
+
+ if (!pygi_arg_sequence_setup (sc, type_info, arg_info, transfer, direction)) {
+ _pygi_arg_cache_free ( (PyGIArgCache *)sc);
+ return NULL;
+ }
+
return sc;
}
+static PyGIArgGArray *
+_arg_array_cache_new (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ gssize child_offset)
+{
+ PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray);
+ if (array_cache == NULL)
+ return NULL;
+
+ if (!pygi_arg_garray_setup (array_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ child_offset)) {
+ _pygi_arg_cache_free ( (PyGIArgCache *)array_cache);
+ return NULL;
+ }
+
+ return array_cache;
+}
+
static PyGICallbackCache *
_callback_cache_new (GIArgInfo *arg_info,
GIInterfaceInfo *iface_info,
@@ -284,7 +364,7 @@ _arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache,
gssize arg_index,
gssize *py_arg_index)
{
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
if (seq_cache->len_arg_index >= 0) {
PyGIArgCache *child_cache = NULL;
@@ -357,7 +437,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
PyGIDirection direction,
gssize arg_index)
{
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
seq_cache->array_type = g_type_info_get_array_type (type_info);
arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
@@ -372,7 +452,7 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
PyGIDirection direction,
gssize arg_index)
{
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
seq_cache->array_type = g_type_info_get_array_type (type_info);
arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
@@ -706,11 +786,12 @@ _arg_cache_new (GITypeInfo *type_info,
case GI_TYPE_TAG_ARRAY:
{
- PyGISequenceCache *seq_cache =
- _sequence_cache_new (type_info,
- direction,
- transfer,
- child_offset);
+ PyGIArgGArray *seq_cache =
+ _arg_array_cache_new (type_info,
+ arg_info,
+ transfer,
+ direction,
+ child_offset);
arg_cache = (PyGIArgCache *)seq_cache;
if (arg_cache == NULL)
@@ -738,15 +819,17 @@ _arg_cache_new (GITypeInfo *type_info,
c_arg_index,
&py_arg_index);
- break;
+ arg_cache->py_arg_index = py_arg_index;
+ arg_cache->c_arg_index = c_arg_index;
+ return arg_cache;
}
case GI_TYPE_TAG_GLIST:
{
PyGISequenceCache *seq_cache =
- _sequence_cache_new (type_info,
- direction,
- transfer,
- child_offset);
+ pygi_arg_sequence_new (type_info,
+ arg_info,
+ transfer,
+ direction);
arg_cache = (PyGIArgCache *)seq_cache;
if (arg_cache == NULL)
@@ -758,16 +841,17 @@ _arg_cache_new (GITypeInfo *type_info,
if (direction & PYGI_DIRECTION_TO_PYTHON)
_arg_cache_to_py_glist_setup (arg_cache, transfer);
-
- break;
+ arg_cache->py_arg_index = py_arg_index;
+ arg_cache->c_arg_index = c_arg_index;
+ return arg_cache;
}
case GI_TYPE_TAG_GSLIST:
{
PyGISequenceCache *seq_cache =
- _sequence_cache_new (type_info,
- direction,
- transfer,
- child_offset);
+ pygi_arg_sequence_new (type_info,
+ arg_info,
+ transfer,
+ direction);
arg_cache = (PyGIArgCache *)seq_cache;
if (arg_cache == NULL)
@@ -779,7 +863,9 @@ _arg_cache_new (GITypeInfo *type_info,
if (direction & PYGI_DIRECTION_TO_PYTHON)
_arg_cache_to_py_gslist_setup (arg_cache, transfer);
- break;
+ arg_cache->py_arg_index = py_arg_index;
+ arg_cache->c_arg_index = c_arg_index;
+ return arg_cache;
}
case GI_TYPE_TAG_GHASH:
arg_cache = pygi_arg_hash_table_new_from_info (type_info, arg_info, transfer, direction);
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 82e25197..0629646a 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -132,13 +132,18 @@ struct _PyGIArgCache
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;
- PyGIArgCache *item_cache;
-} PyGISequenceCache;
+} PyGIArgGArray;
typedef struct _PyGIInterfaceCache
{
@@ -211,6 +216,13 @@ pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache,
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);
+
PyGIArgCache * _arg_cache_alloc (void);
PyGIArgCache * _arg_cache_new (GITypeInfo *type_info,
GIArgInfo *arg_info,
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 675b0ef3..151c9e5e 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -422,9 +422,9 @@ static gboolean _caller_alloc (PyGIInvokeState *state,
state->args[arg_count]->v_pointer = g_malloc0 (size);
}
} else if (arg_cache->type_tag == GI_TYPE_TAG_ARRAY) {
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
- state->out_args[out_count].v_pointer = g_array_new (TRUE, TRUE, seq_cache->item_size);
+ state->out_args[out_count].v_pointer = g_array_new (TRUE, TRUE, array_cache->item_size);
state->args[arg_count] = &state->out_args[out_count];
} else {
return FALSE;
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
index 0bf08a9c..52d7bb38 100644
--- a/gi/pygi-marshal-cleanup.c
+++ b/gi/pygi-marshal-cleanup.c
@@ -297,24 +297,24 @@ _pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
static GArray*
_wrap_c_array (PyGIInvokeState *state,
- PyGISequenceCache *sequence_cache,
+ PyGIArgGArray *array_cache,
gpointer data)
{
GArray *array_;
gsize len = 0;
- if (sequence_cache->fixed_size >= 0) {
- len = sequence_cache->fixed_size;
- } else if (sequence_cache->is_zero_terminated) {
+ if (array_cache->fixed_size >= 0) {
+ len = array_cache->fixed_size;
+ } else if (array_cache->is_zero_terminated) {
len = g_strv_length ((gchar **)data);
- } else if (sequence_cache->len_arg_index >= 0) {
- GIArgument *len_arg = state->args[sequence_cache->len_arg_index];
+ } else if (array_cache->len_arg_index >= 0) {
+ GIArgument *len_arg = state->args[array_cache->len_arg_index];
len = len_arg->v_long;
}
array_ = g_array_new (FALSE,
FALSE,
- sequence_cache->item_size);
+ array_cache->item_size);
if (array_ == NULL)
return NULL;
@@ -337,8 +337,9 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
GArray *array_ = NULL;
GPtrArray *ptr_array_ = NULL;
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
- if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
ptr_array_ = (GPtrArray *) data;
} else {
array_ = (GArray *) data;
@@ -363,7 +364,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
item = g_array_index (array_, gpointer, i);
/* case 3: C array or GArray with simple types or structs */
else {
- item = array_->data + i * sequence_cache->item_size;
+ item = array_->data + i * array_cache->item_size;
/* special-case hack: GValue array items do not get slice
* allocated in _pygi_marshal_from_py_array(), so we must
* not try to deallocate it as a slice and thus
@@ -381,7 +382,7 @@ _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) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
/* always free the GArray wrapper created in from_py marshaling and
* passed back as cleanup_data
*/
@@ -407,16 +408,17 @@ _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
GArray *array_ = NULL;
GPtrArray *ptr_array_ = NULL;
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)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_cache->array_type == GI_ARRAY_TYPE_C) {
+ array_ = _wrap_c_array (state, array_cache, data);
if (array_ == NULL)
return;
- } else if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
ptr_array_ = (GPtrArray *) data;
} else {
array_ = (GArray *) data;
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index b143727c..3867c233 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -258,6 +258,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
gboolean is_ptr_array;
GArray *array_ = NULL;
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
if (py_arg == Py_None) {
@@ -275,20 +276,20 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
if (length < 0)
return FALSE;
- if (sequence_cache->fixed_size >= 0 &&
- sequence_cache->fixed_size != length) {
+ if (array_cache->fixed_size >= 0 &&
+ array_cache->fixed_size != length) {
PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- sequence_cache->fixed_size, length);
+ array_cache->fixed_size, length);
return FALSE;
}
- item_size = sequence_cache->item_size;
- is_ptr_array = (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
+ item_size = array_cache->item_size;
+ is_ptr_array = (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
if (is_ptr_array) {
array_ = (GArray *)g_ptr_array_sized_new (length);
} else {
- array_ = g_array_sized_new (sequence_cache->is_zero_terminated,
+ array_ = g_array_sized_new (array_cache->is_zero_terminated,
TRUE,
item_size,
length);
@@ -303,7 +304,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
PYGLIB_PyBytes_Check (py_arg)) {
memcpy(array_->data, PYGLIB_PyBytes_AsString (py_arg), length);
array_->len = length;
- if (sequence_cache->is_zero_terminated) {
+ if (array_cache->is_zero_terminated) {
/* If array_ has been created with zero_termination, space for the
* terminator is properly allocated, so we're not off-by-one here. */
array_->data[length] = '\0';
@@ -433,10 +434,10 @@ err:
}
array_success:
- if (sequence_cache->len_arg_index >= 0) {
+ if (array_cache->len_arg_index >= 0) {
/* we have an child arg to handle */
PyGIArgCache *child_cache =
- _pygi_callable_cache_get_arg (callable_cache, sequence_cache->len_arg_index);
+ _pygi_callable_cache_get_arg (callable_cache, array_cache->len_arg_index);
if (child_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL) {
gint *len_arg = (gint *)state->in_args[child_cache->c_arg_index].v_pointer;
@@ -459,7 +460,7 @@ array_success:
}
}
- if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
/* 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.
@@ -523,14 +524,6 @@ _pygi_marshal_from_py_glist (PyGIInvokeState *state,
if (length < 0)
return FALSE;
- if (sequence_cache->fixed_size >= 0 &&
- sequence_cache->fixed_size != length) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- sequence_cache->fixed_size, length);
-
- return FALSE;
- }
-
from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
for (i = 0; i < length; i++) {
GIArgument item = {0};
@@ -607,14 +600,6 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState *state,
if (length < 0)
return FALSE;
- if (sequence_cache->fixed_size >= 0 &&
- sequence_cache->fixed_size != length) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- sequence_cache->fixed_size, length);
-
- return FALSE;
- }
-
from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
for (i = 0; i < length; i++) {
GIArgument item = {0};
diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c
index 292f9628..e3d5475d 100644
--- a/gi/pygi-marshal-to-py.c
+++ b/gi/pygi-marshal-to-py.c
@@ -121,18 +121,19 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
GArray *array_;
PyObject *py_obj = NULL;
PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
gsize processed_items = 0;
/* GArrays make it easier to iterate over arrays
* with different element sizes but requires that
* we allocate a GArray if the argument was a C array
*/
- if (seq_cache->array_type == GI_ARRAY_TYPE_C) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
gsize len;
- if (seq_cache->fixed_size >= 0) {
+ if (array_cache->fixed_size >= 0) {
g_assert(arg->v_pointer != NULL);
- len = seq_cache->fixed_size;
- } else if (seq_cache->is_zero_terminated) {
+ len = array_cache->fixed_size;
+ } else if (array_cache->is_zero_terminated) {
if (arg->v_pointer == NULL) {
len = 0;
} else if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
@@ -141,9 +142,9 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
len = g_strv_length ((gchar **)arg->v_pointer);
}
} else {
- GIArgument *len_arg = state->args[seq_cache->len_arg_index];
+ GIArgument *len_arg = state->args[array_cache->len_arg_index];
PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache,
- seq_cache->len_arg_index);
+ array_cache->len_arg_index);
if (!gi_argument_to_gsize (len_arg, &len, arg_cache->type_tag)) {
return NULL;
@@ -152,7 +153,7 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
array_ = g_array_new (FALSE,
FALSE,
- seq_cache->item_size);
+ array_cache->item_size);
if (array_ == NULL) {
PyErr_NoMemory ();
@@ -204,7 +205,7 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
* and move on, letting the per-item marshaler deal with the
* various transfer modes and ref counts (e.g. g_variant_ref_sink).
*/
- if (seq_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
} else if (item_arg_cache->is_pointer) {
@@ -243,7 +244,7 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
if (py_item == NULL) {
Py_CLEAR (py_obj);
- if (seq_cache->array_type == GI_ARRAY_TYPE_C)
+ if (array_cache->array_type == GI_ARRAY_TYPE_C)
g_array_unref (array_);
goto err;
@@ -254,13 +255,13 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
}
}
- if (seq_cache->array_type == GI_ARRAY_TYPE_C)
+ if (array_cache->array_type == GI_ARRAY_TYPE_C)
g_array_free (array_, FALSE);
return py_obj;
err:
- if (seq_cache->array_type == GI_ARRAY_TYPE_C) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING);
} else {
/* clean up unprocessed items */