Imported Upstream version 3.11.5
[platform/upstream/python-gobject.git] / gi / pygi-array.c
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * vim: tabstop=4 shiftwidth=4 expandtab
3  *
4  * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
5  * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <glib.h>
22 #include <Python.h>
23 #include <pyglib-python-compat.h>
24
25 #include "pygi-array.h"
26 #include "pygi-private.h"
27 #include "pygi-marshal-cleanup.h"
28
29 /* Needed for _pygi_marshal_cleanup_from_py_interface_struct_gvalue hack */
30 #include "pygi-struct-marshal.h"
31
32 /*
33  * GArray to Python
34  */
35
36 static gboolean
37 gi_argument_from_py_ssize_t (GIArgument   *arg_out,
38                              Py_ssize_t    size_in,
39                              GITypeTag     type_tag)
40 {
41     switch (type_tag) {
42     case GI_TYPE_TAG_VOID:
43     case GI_TYPE_TAG_BOOLEAN:
44         goto unhandled_type;
45
46     case GI_TYPE_TAG_INT8:
47         if (size_in >= G_MININT8 && size_in <= G_MAXINT8) {
48             arg_out->v_int8 = size_in;
49             return TRUE;
50         } else {
51             goto overflow;
52         }
53
54     case GI_TYPE_TAG_UINT8:
55         if (size_in >= 0 && size_in <= G_MAXUINT8) {
56             arg_out->v_uint8 = size_in;
57             return TRUE;
58         } else {
59             goto overflow;
60         }
61
62     case GI_TYPE_TAG_INT16:
63         if (size_in >= G_MININT16 && size_in <= G_MAXINT16) {
64             arg_out->v_int16 = size_in;
65             return TRUE;
66         } else {
67             goto overflow;
68         }
69
70     case GI_TYPE_TAG_UINT16:
71         if (size_in >= 0 && size_in <= G_MAXUINT16) {
72             arg_out->v_uint16 = size_in;
73             return TRUE;
74         } else {
75             goto overflow;
76         }
77
78         /* Ranges assume two's complement */
79     case GI_TYPE_TAG_INT32:
80         if (size_in >= G_MININT32 && size_in <= G_MAXINT32) {
81             arg_out->v_int32 = size_in;
82             return TRUE;
83         } else {
84             goto overflow;
85         }
86
87     case GI_TYPE_TAG_UINT32:
88         if (size_in >= 0 && size_in <= G_MAXUINT32) {
89             arg_out->v_uint32 = size_in;
90             return TRUE;
91         } else {
92             goto overflow;
93         }
94
95     case GI_TYPE_TAG_INT64:
96         arg_out->v_int64 = size_in;
97         return TRUE;
98
99     case GI_TYPE_TAG_UINT64:
100         if (size_in >= 0) {
101             arg_out->v_uint64 = size_in;
102             return TRUE;
103         } else {
104             goto overflow;
105         }
106
107     case GI_TYPE_TAG_FLOAT:
108     case GI_TYPE_TAG_DOUBLE:
109     case GI_TYPE_TAG_GTYPE:
110     case GI_TYPE_TAG_UTF8:
111     case GI_TYPE_TAG_FILENAME:
112     case GI_TYPE_TAG_ARRAY:
113     case GI_TYPE_TAG_INTERFACE:
114     case GI_TYPE_TAG_GLIST:
115     case GI_TYPE_TAG_GSLIST:
116     case GI_TYPE_TAG_GHASH:
117     case GI_TYPE_TAG_ERROR:
118     case GI_TYPE_TAG_UNICHAR:
119     default:
120         goto unhandled_type;
121     }
122
123  overflow:
124     PyErr_Format (PyExc_OverflowError,
125                   "Unable to marshal C Py_ssize_t %zd to %s",
126                   size_in,
127                   g_type_tag_to_string (type_tag));
128     return FALSE;
129
130  unhandled_type:
131     PyErr_Format (PyExc_TypeError,
132                   "Unable to marshal C Py_ssize_t %zd to %s",
133                   size_in,
134                   g_type_tag_to_string (type_tag));
135     return FALSE;
136 }
137
138 static gboolean
139 gi_argument_to_gsize (GIArgument *arg_in,
140                       gsize      *gsize_out,
141                       GITypeTag   type_tag)
142 {
143     switch (type_tag) {
144       case GI_TYPE_TAG_INT8:
145           *gsize_out = arg_in->v_int8;
146           return TRUE;
147       case GI_TYPE_TAG_UINT8:
148           *gsize_out = arg_in->v_uint8;
149           return TRUE;
150       case GI_TYPE_TAG_INT16:
151           *gsize_out = arg_in->v_int16;
152           return TRUE;
153       case GI_TYPE_TAG_UINT16:
154           *gsize_out = arg_in->v_uint16;
155           return TRUE;
156       case GI_TYPE_TAG_INT32:
157           *gsize_out = arg_in->v_int32;
158           return TRUE;
159       case GI_TYPE_TAG_UINT32:
160           *gsize_out = arg_in->v_uint32;
161           return TRUE;
162       case GI_TYPE_TAG_INT64:
163           *gsize_out = arg_in->v_int64;
164           return TRUE;
165       case GI_TYPE_TAG_UINT64:
166           *gsize_out = arg_in->v_uint64;
167           return TRUE;
168       default:
169           PyErr_Format (PyExc_TypeError,
170                         "Unable to marshal %s to gsize",
171                         g_type_tag_to_string (type_tag));
172           return FALSE;
173     }
174 }
175
176 static gboolean
177 _pygi_marshal_from_py_array (PyGIInvokeState   *state,
178                              PyGICallableCache *callable_cache,
179                              PyGIArgCache      *arg_cache,
180                              PyObject          *py_arg,
181                              GIArgument        *arg,
182                              gpointer          *cleanup_data)
183 {
184     PyGIMarshalFromPyFunc from_py_marshaller;
185     int i = 0;
186     int success_count = 0;
187     Py_ssize_t length;
188     gssize item_size;
189     gboolean is_ptr_array;
190     GArray *array_ = NULL;
191     PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
192     PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
193
194
195     if (py_arg == Py_None) {
196         arg->v_pointer = NULL;
197         return TRUE;
198     }
199
200     if (!PySequence_Check (py_arg)) {
201         PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
202                       py_arg->ob_type->tp_name);
203         return FALSE;
204     }
205
206     length = PySequence_Length (py_arg);
207     if (length < 0)
208         return FALSE;
209
210     if (array_cache->fixed_size >= 0 &&
211             array_cache->fixed_size != length) {
212         PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
213                       array_cache->fixed_size, length);
214
215         return FALSE;
216     }
217
218     item_size = array_cache->item_size;
219     is_ptr_array = (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
220     if (is_ptr_array) {
221         array_ = (GArray *)g_ptr_array_sized_new (length);
222     } else {
223         array_ = g_array_sized_new (array_cache->is_zero_terminated,
224                                     TRUE,
225                                     item_size,
226                                     length);
227     }
228
229     if (array_ == NULL) {
230         PyErr_NoMemory ();
231         return FALSE;
232     }
233
234     if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8 &&
235         PYGLIB_PyBytes_Check (py_arg)) {
236         memcpy(array_->data, PYGLIB_PyBytes_AsString (py_arg), length);
237         array_->len = length;
238         if (array_cache->is_zero_terminated) {
239             /* If array_ has been created with zero_termination, space for the
240              * terminator is properly allocated, so we're not off-by-one here. */
241             array_->data[length] = '\0';
242         }
243         goto array_success;
244     }
245
246     from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
247     for (i = 0, success_count = 0; i < length; i++) {
248         GIArgument item = {0};
249         gpointer item_cleanup_data = NULL;
250         PyObject *py_item = PySequence_GetItem (py_arg, i);
251         if (py_item == NULL)
252             goto err;
253
254         if (!from_py_marshaller ( state,
255                                   callable_cache,
256                                   sequence_cache->item_cache,
257                                   py_item,
258                                  &item,
259                                  &item_cleanup_data)) {
260             Py_DECREF (py_item);
261             goto err;
262         }
263         Py_DECREF (py_item);
264
265         if (item_cleanup_data != NULL && item_cleanup_data != item.v_pointer) {
266             /* We only support one level of data discrepancy between an items
267              * data and its cleanup data. This is because we only track a single
268              * extra cleanup data pointer per-argument and cannot track the entire
269              * array of items differing data and cleanup_data.
270              * For example, this would fail if trying to marshal an array of
271              * callback closures marked with SCOPE call type where the cleanup data
272              * is different from the items v_pointer, likewise an array of arrays.
273              */
274             PyErr_SetString(PyExc_RuntimeError, "Cannot cleanup item data for array due to "
275                                                 "the items data its cleanup data being different.");
276             goto err;
277         }
278
279         /* FIXME: it is much more efficent to have seperate marshaller
280          *        for ptr arrays than doing the evaluation
281          *        and casting each loop iteration
282          */
283         if (is_ptr_array) {
284             g_ptr_array_add((GPtrArray *)array_, item.v_pointer);
285         } else if (sequence_cache->item_cache->is_pointer) {
286             /* if the item is a pointer, simply copy the pointer */
287             g_assert (item_size == sizeof (item.v_pointer));
288             g_array_insert_val (array_, i, item);
289         } else if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
290             /* Special case handling of flat arrays of gvalue/boxed/struct */
291             PyGIInterfaceCache *item_iface_cache = (PyGIInterfaceCache *) sequence_cache->item_cache;
292             GIBaseInfo *base_info = (GIBaseInfo *) item_iface_cache->interface_info;
293             GIInfoType info_type = g_base_info_get_type (base_info);
294
295             switch (info_type) {
296                 case GI_INFO_TYPE_UNION:
297                 case GI_INFO_TYPE_STRUCT:
298                 {
299                     PyGIArgCache *item_arg_cache = (PyGIArgCache *)item_iface_cache;
300                     PyGIMarshalCleanupFunc from_py_cleanup = item_arg_cache->from_py_cleanup;
301
302                     if (g_type_is_a (item_iface_cache->g_type, G_TYPE_VALUE)) {
303                         /* Special case GValue flat arrays to properly init and copy the contents. */
304                         GValue* dest = (GValue*) (array_->data + (i * item_size));
305                         if (item.v_pointer != NULL) {
306                             memset (dest, 0, item_size);
307                             g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
308                             g_value_copy ((GValue*) item.v_pointer, dest);
309                         }
310                         /* Manually increment the length because we are manually setting the memory. */
311                         array_->len++;
312
313                     } else {
314                         /* Handles flat arrays of boxed or struct types. */
315                         g_array_insert_vals (array_, i, item.v_pointer, 1);
316                     }
317
318                     /* Cleanup any memory left by the per-item marshaler because
319                      * _pygi_marshal_cleanup_from_py_array will not know about this
320                      * due to "item" being a temporarily marshaled value done on the stack.
321                      */
322                     if (from_py_cleanup)
323                         from_py_cleanup (state, item_arg_cache, py_item, item_cleanup_data, TRUE);
324
325                     break;
326                 }
327                 default:
328                     g_array_insert_val (array_, i, item);
329             }
330         } else {
331             /* default value copy of a simple type */
332             g_array_insert_val (array_, i, item);
333         }
334
335         success_count++;
336         continue;
337 err:
338         if (sequence_cache->item_cache->from_py_cleanup != NULL) {
339             gsize j;
340             PyGIMarshalCleanupFunc cleanup_func =
341                 sequence_cache->item_cache->from_py_cleanup;
342
343             /* Only attempt per item cleanup on pointer items */
344             if (sequence_cache->item_cache->is_pointer) {
345                 for(j = 0; j < success_count; j++) {
346                     PyObject *py_item = PySequence_GetItem (py_arg, j);
347                     cleanup_func (state,
348                                   sequence_cache->item_cache,
349                                   py_item,
350                                   is_ptr_array ?
351                                           g_ptr_array_index ((GPtrArray *)array_, j) :
352                                           g_array_index (array_, gpointer, j),
353                                   TRUE);
354                     Py_DECREF (py_item);
355                 }
356             }
357         }
358
359         if (is_ptr_array)
360             g_ptr_array_free ( ( GPtrArray *)array_, TRUE);
361         else
362             g_array_free (array_, TRUE);
363         _PyGI_ERROR_PREFIX ("Item %i: ", i);
364         return FALSE;
365     }
366
367 array_success:
368     if (array_cache->len_arg_index >= 0) {
369         /* we have an child arg to handle */
370         PyGIArgCache *child_cache =
371             _pygi_callable_cache_get_arg (callable_cache, array_cache->len_arg_index);
372
373         if (child_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL) {
374             gint *len_arg = (gint *)state->in_args[child_cache->c_arg_index].v_pointer;
375             /* if we are not setup yet just set the in arg */
376             if (len_arg == NULL) {
377                 if (!gi_argument_from_py_ssize_t (&state->in_args[child_cache->c_arg_index],
378                                                   length,
379                                                   child_cache->type_tag)) {
380                     goto err;
381                 }
382             } else {
383                 *len_arg = length;
384             }
385         } else {
386             if (!gi_argument_from_py_ssize_t (&state->in_args[child_cache->c_arg_index],
387                                               length,
388                                               child_cache->type_tag)) {
389                 goto err;
390             }
391         }
392     }
393
394     if (array_cache->array_type == GI_ARRAY_TYPE_C) {
395         /* In the case of GI_ARRAY_C, we give the data directly as the argument
396          * but keep the array_ wrapper as cleanup data so we don't have to find
397          * it's length again.
398          */
399         arg->v_pointer = array_->data;
400
401         if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
402             g_array_free (array_, FALSE);
403             *cleanup_data = NULL;
404         } else {
405             *cleanup_data = array_;
406         }
407     } else {
408         arg->v_pointer = array_;
409
410         if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
411             /* Free everything in cleanup. */
412             *cleanup_data = array_;
413         } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
414             /* Make a shallow copy so we can free the elements later in cleanup
415              * because it is possible invoke will free the list before our cleanup. */
416             *cleanup_data = is_ptr_array ?
417                     (gpointer)g_ptr_array_ref ((GPtrArray *)array_) :
418                     (gpointer)g_array_ref (array_);
419         } else { /* GI_TRANSFER_EVERYTHING */
420             /* No cleanup, everything is given to the callee. */
421             *cleanup_data = NULL;
422         }
423     }
424
425     return TRUE;
426 }
427
428 static void
429 _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
430                                      PyGIArgCache    *arg_cache,
431                                      PyObject        *py_arg,
432                                      gpointer         data,
433                                      gboolean         was_processed)
434 {
435     if (was_processed) {
436         GArray *array_ = NULL;
437         GPtrArray *ptr_array_ = NULL;
438         PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
439         PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
440
441         if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
442             ptr_array_ = (GPtrArray *) data;
443         } else {
444             array_ = (GArray *) data;
445         }
446
447         /* clean up items first */
448         if (sequence_cache->item_cache->from_py_cleanup != NULL) {
449             gsize i;
450             guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
451             PyGIMarshalCleanupFunc cleanup_func =
452                 sequence_cache->item_cache->from_py_cleanup;
453
454             for (i = 0; i < len; i++) {
455                 gpointer item;
456                 PyObject *py_item = NULL;
457
458                 /* case 1: GPtrArray */
459                 if (ptr_array_ != NULL)
460                     item = g_ptr_array_index (ptr_array_, i);
461                 /* case 2: C array or GArray with object pointers */
462                 else if (sequence_cache->item_cache->is_pointer)
463                     item = g_array_index (array_, gpointer, i);
464                 /* case 3: C array or GArray with simple types or structs */
465                 else {
466                     item = array_->data + i * array_cache->item_size;
467                     /* special-case hack: GValue array items do not get slice
468                      * allocated in _pygi_marshal_from_py_array(), so we must
469                      * not try to deallocate it as a slice and thus
470                      * short-circuit cleanup_func. */
471                     if (cleanup_func == _pygi_marshal_cleanup_from_py_interface_struct_gvalue) {
472                         g_value_unset ((GValue*) item);
473                         continue;
474                     }
475                 }
476
477                 py_item = PySequence_GetItem (py_arg, i);
478                 cleanup_func (state, sequence_cache->item_cache, py_item, item, TRUE);
479                 Py_XDECREF (py_item);
480             }
481         }
482
483         /* Only free the array when we didn't transfer ownership */
484         if (array_cache->array_type == GI_ARRAY_TYPE_C) {
485             /* always free the GArray wrapper created in from_py marshaling and
486              * passed back as cleanup_data
487              */
488             g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING);
489         } else {
490             if (array_ != NULL)
491                 g_array_unref (array_);
492             else
493                 g_ptr_array_unref (ptr_array_);
494         }
495     }
496 }
497
498 /*
499  * GArray from Python
500  */
501 static PyObject *
502 _pygi_marshal_to_py_array (PyGIInvokeState   *state,
503                            PyGICallableCache *callable_cache,
504                            PyGIArgCache      *arg_cache,
505                            GIArgument        *arg)
506 {
507     GArray *array_;
508     PyObject *py_obj = NULL;
509     PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
510     PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
511     gsize processed_items = 0;
512
513      /* GArrays make it easier to iterate over arrays
514       * with different element sizes but requires that
515       * we allocate a GArray if the argument was a C array
516       */
517     if (array_cache->array_type == GI_ARRAY_TYPE_C) {
518         gsize len;
519         if (array_cache->fixed_size >= 0) {
520             g_assert(arg->v_pointer != NULL);
521             len = array_cache->fixed_size;
522         } else if (array_cache->is_zero_terminated) {
523             if (arg->v_pointer == NULL) {
524                 len = 0;
525             } else if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
526                 len = strlen (arg->v_pointer);
527             } else {
528                 len = g_strv_length ((gchar **)arg->v_pointer);
529             }
530         } else {
531             GIArgument *len_arg = state->args[array_cache->len_arg_index];
532             PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache,
533                                                                     array_cache->len_arg_index);
534
535             if (!gi_argument_to_gsize (len_arg, &len, arg_cache->type_tag)) {
536                 return NULL;
537             }
538         }
539
540         array_ = g_array_new (FALSE,
541                               FALSE,
542                               array_cache->item_size);
543         if (array_ == NULL) {
544             PyErr_NoMemory ();
545
546             if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && arg->v_pointer != NULL)
547                 g_free (arg->v_pointer);
548
549             return NULL;
550         }
551
552         if (array_->data != NULL)
553             g_free (array_->data);
554         array_->data = arg->v_pointer;
555         array_->len = len;
556     } else {
557         array_ = arg->v_pointer;
558     }
559
560     if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
561         if (arg->v_pointer == NULL) {
562             py_obj = PYGLIB_PyBytes_FromString ("");
563         } else {
564             py_obj = PYGLIB_PyBytes_FromStringAndSize (array_->data, array_->len);
565         }
566     } else {
567         if (arg->v_pointer == NULL) {
568             py_obj = PyList_New (0);
569         } else {
570             int i;
571
572             gsize item_size;
573             PyGIMarshalToPyFunc item_to_py_marshaller;
574             PyGIArgCache *item_arg_cache;
575
576             py_obj = PyList_New (array_->len);
577             if (py_obj == NULL)
578                 goto err;
579
580
581             item_arg_cache = seq_cache->item_cache;
582             item_to_py_marshaller = item_arg_cache->to_py_marshaller;
583
584             item_size = g_array_get_element_size (array_);
585
586             for (i = 0; i < array_->len; i++) {
587                 GIArgument item_arg = {0};
588                 PyObject *py_item;
589
590                 /* If we are receiving an array of pointers, simply assign the pointer
591                  * and move on, letting the per-item marshaler deal with the
592                  * various transfer modes and ref counts (e.g. g_variant_ref_sink).
593                  */
594                 if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
595                     item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
596
597                 } else if (item_arg_cache->is_pointer) {
598                     item_arg.v_pointer = g_array_index (array_, gpointer, i);
599
600                 } else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
601                     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *) item_arg_cache;
602
603                     // FIXME: This probably doesn't work with boxed types or gvalues. See fx. _pygi_marshal_from_py_array()
604                     switch (g_base_info_get_type (iface_cache->interface_info)) {
605                         case GI_INFO_TYPE_STRUCT:
606                             if (arg_cache->transfer == GI_TRANSFER_EVERYTHING &&
607                                        !g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
608                                 /* array elements are structs */
609                                 gpointer *_struct = g_malloc (item_size);
610                                 memcpy (_struct, array_->data + i * item_size,
611                                         item_size);
612                                 item_arg.v_pointer = _struct;
613                             } else {
614                                 item_arg.v_pointer = array_->data + i * item_size;
615                             }
616                             break;
617                         default:
618                             item_arg.v_pointer = g_array_index (array_, gpointer, i);
619                             break;
620                     }
621                 } else {
622                     memcpy (&item_arg, array_->data + i * item_size, item_size);
623                 }
624
625                 py_item = item_to_py_marshaller ( state,
626                                                 callable_cache,
627                                                 item_arg_cache,
628                                                 &item_arg);
629
630                 if (py_item == NULL) {
631                     Py_CLEAR (py_obj);
632
633                     if (array_cache->array_type == GI_ARRAY_TYPE_C)
634                         g_array_unref (array_);
635
636                     goto err;
637                 }
638                 PyList_SET_ITEM (py_obj, i, py_item);
639                 processed_items++;
640             }
641         }
642     }
643
644     if (array_cache->array_type == GI_ARRAY_TYPE_C)
645         g_array_free (array_, FALSE);
646
647     return py_obj;
648
649 err:
650     if (array_cache->array_type == GI_ARRAY_TYPE_C) {
651         g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING);
652     } else {
653         /* clean up unprocessed items */
654         if (seq_cache->item_cache->to_py_cleanup != NULL) {
655             int j;
656             PyGIMarshalCleanupFunc cleanup_func = seq_cache->item_cache->to_py_cleanup;
657             for (j = processed_items; j < array_->len; j++) {
658                 cleanup_func (state,
659                               seq_cache->item_cache,
660                               NULL,
661                               g_array_index (array_, gpointer, j),
662                               FALSE);
663             }
664         }
665
666         if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
667             g_array_free (array_, TRUE);
668     }
669
670     return NULL;
671 }
672
673 static GArray*
674 _wrap_c_array (PyGIInvokeState   *state,
675                PyGIArgGArray     *array_cache,
676                gpointer           data)
677 {
678     GArray *array_;
679     gsize   len = 0;
680
681     if (array_cache->fixed_size >= 0) {
682         len = array_cache->fixed_size;
683     } else if (array_cache->is_zero_terminated) {
684         len = g_strv_length ((gchar **)data);
685     } else if (array_cache->len_arg_index >= 0) {
686         GIArgument *len_arg = state->args[array_cache->len_arg_index];
687         len = len_arg->v_long;
688     }
689
690     array_ = g_array_new (FALSE,
691                           FALSE,
692                           array_cache->item_size);
693
694     if (array_ == NULL)
695         return NULL;
696
697     g_free (array_->data);
698     array_->data = data;
699     array_->len = len;
700
701     return array_;
702 }
703
704 static void
705 _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
706                                    PyGIArgCache    *arg_cache,
707                                    PyObject        *dummy,
708                                    gpointer         data,
709                                    gboolean         was_processed)
710 {
711     if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
712         arg_cache->transfer == GI_TRANSFER_CONTAINER) {
713         GArray *array_ = NULL;
714         GPtrArray *ptr_array_ = NULL;
715         PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
716         PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
717
718         /* If this isn't a garray create one to help process variable sized
719            array elements */
720         if (array_cache->array_type == GI_ARRAY_TYPE_C) {
721             array_ = _wrap_c_array (state, array_cache, data);
722
723             if (array_ == NULL)
724                 return;
725
726         } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
727             ptr_array_ = (GPtrArray *) data;
728         } else {
729             array_ = (GArray *) data;
730         }
731
732         if (sequence_cache->item_cache->to_py_cleanup != NULL) {
733             gsize i;
734             guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
735
736             PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
737             for (i = 0; i < len; i++) {
738                 cleanup_func (state,
739                               sequence_cache->item_cache,
740                               NULL,
741                               (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
742                               was_processed);
743             }
744         }
745
746         if (array_ != NULL)
747             g_array_free (array_, TRUE);
748         else
749             g_ptr_array_free (ptr_array_, TRUE);
750     }
751 }
752
753 static void
754 _array_cache_free_func (PyGIArgGArray *cache)
755 {
756     if (cache != NULL) {
757         pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache);
758         g_slice_free (PyGIArgGArray, cache);
759     }
760 }
761
762 PyGIArgCache*
763 pygi_arg_garray_len_arg_setup (PyGIArgCache *arg_cache,
764                                GITypeInfo *type_info,
765                                PyGICallableCache *callable_cache,
766                                PyGIDirection direction,
767                                gssize arg_index,
768                                gssize *py_arg_index)
769 {
770     PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
771
772     /* attempt len_arg_index setup for the first time */
773     if (seq_cache->len_arg_index < 0) {
774         seq_cache->len_arg_index = g_type_info_get_array_length (type_info);
775
776         /* offset by self arg for methods and vfuncs */
777         if (seq_cache->len_arg_index >= 0 && callable_cache != NULL &&
778                 (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
779                  callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC)) {
780             seq_cache->len_arg_index += 1;
781         }
782     }
783
784     if (seq_cache->len_arg_index >= 0) {
785         PyGIArgCache *child_cache = NULL;
786
787         child_cache = _pygi_callable_cache_get_arg (callable_cache,
788                                                     seq_cache->len_arg_index);
789         if (child_cache == NULL) {
790             child_cache = pygi_arg_cache_alloc ();
791         } else {
792             /* If the "length" arg cache already exists (the length comes before
793              * the array in the argument list), remove it from the to_py_args list
794              * because it does not belong in "to python" return tuple. The length
795              * will implicitly be a part of the returned Python list.
796              */
797             if (direction & PYGI_DIRECTION_TO_PYTHON) {
798                 callable_cache->to_py_args =
799                     g_slist_remove (callable_cache->to_py_args, child_cache);
800             }
801
802             /* This is a case where the arg cache already exists and has been
803              * setup by another array argument sharing the same length argument.
804              * See: gi_marshalling_tests_multi_array_key_value_in
805              */
806             if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
807                 return child_cache;
808         }
809
810         /* There is a length argument for this array, so increment the number
811          * of "to python" child arguments when applicable.
812          */
813         if (direction & PYGI_DIRECTION_TO_PYTHON)
814              callable_cache->n_to_py_child_args++;
815
816         child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
817         child_cache->direction = direction;
818         child_cache->to_py_marshaller = NULL;
819         child_cache->from_py_marshaller = NULL;
820
821         /* ugly edge case code:
822          *
823          * When the length comes before the array parameter we need to update
824          * indexes of arguments after the index argument.
825          */
826         if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
827             gssize i;
828             (*py_arg_index) -= 1;
829             callable_cache->n_py_args -= 1;
830
831             for (i = seq_cache->len_arg_index + 1;
832                    i < _pygi_callable_cache_args_len (callable_cache); i++) {
833                 PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
834                 if (update_cache == NULL)
835                     break;
836
837                 update_cache->py_arg_index -= 1;
838             }
839         }
840
841         _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
842         return child_cache;
843     }
844
845     return NULL;
846 }
847
848 static gboolean
849 pygi_arg_garray_setup (PyGIArgGArray      *sc,
850                        GITypeInfo         *type_info,
851                        GIArgInfo          *arg_info,    /* may be NULL for return arguments */
852                        GITransfer          transfer,
853                        PyGIDirection       direction)
854 {
855     GITypeInfo *item_type_info;
856     PyGIArgCache *arg_cache = (PyGIArgCache *)sc;
857
858     if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc,
859                                   type_info,
860                                   arg_info,
861                                   transfer,
862                                   direction)) {
863         return FALSE;
864     }
865
866     ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func;
867     sc->array_type = g_type_info_get_array_type (type_info);
868     sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
869     sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
870     sc->len_arg_index = -1;  /* setup by pygi_arg_garray_len_arg_setup */
871
872     item_type_info = g_type_info_get_param_type (type_info, 0);
873     sc->item_size = _pygi_g_type_info_size (item_type_info);
874     g_base_info_unref ( (GIBaseInfo *)item_type_info);
875
876     if (direction & PYGI_DIRECTION_FROM_PYTHON) {
877         arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
878         arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
879     }
880
881     if (direction & PYGI_DIRECTION_TO_PYTHON) {
882         arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
883         arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
884     }
885
886     return TRUE;
887 }
888
889 PyGIArgCache *
890 pygi_arg_garray_new_from_info (GITypeInfo *type_info,
891                                GIArgInfo *arg_info,
892                                GITransfer transfer,
893                                PyGIDirection direction)
894 {
895     PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray);
896     if (array_cache == NULL)
897         return NULL;
898
899     if (!pygi_arg_garray_setup (array_cache,
900                                 type_info,
901                                 arg_info,
902                                 transfer,
903                                 direction)) {
904         pygi_arg_cache_free ( (PyGIArgCache *)array_cache);
905         return NULL;
906     }
907
908     return (PyGIArgCache *)array_cache;
909 }