1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * vim: tabstop=4 shiftwidth=4 expandtab
4 * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
5 * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
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.
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.
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/>.
24 #include "pygi-python-compat.h"
25 #include "pygi-array.h"
26 #include "pygi-info.h"
27 #include "pygi-marshal-cleanup.h"
28 #include "pygi-basictype.h"
29 #include "pygi-util.h"
31 /* Needed for _pygi_marshal_cleanup_from_py_interface_struct_gvalue hack */
32 #include "pygi-struct-marshal.h"
39 gi_argument_from_py_ssize_t (GIArgument *arg_out,
44 case GI_TYPE_TAG_VOID:
45 case GI_TYPE_TAG_BOOLEAN:
48 case GI_TYPE_TAG_INT8:
49 if (size_in >= G_MININT8 && size_in <= G_MAXINT8) {
50 arg_out->v_int8 = (gint8)size_in;
56 case GI_TYPE_TAG_UINT8:
57 if (size_in >= 0 && size_in <= G_MAXUINT8) {
58 arg_out->v_uint8 = (guint8)size_in;
64 case GI_TYPE_TAG_INT16:
65 if (size_in >= G_MININT16 && size_in <= G_MAXINT16) {
66 arg_out->v_int16 = (gint16)size_in;
72 case GI_TYPE_TAG_UINT16:
73 if (size_in >= 0 && size_in <= G_MAXUINT16) {
74 arg_out->v_uint16 = (guint16)size_in;
80 /* Ranges assume two's complement */
81 case GI_TYPE_TAG_INT32:
82 if (size_in >= G_MININT32 && size_in <= G_MAXINT32) {
83 arg_out->v_int32 = (gint32)size_in;
89 case GI_TYPE_TAG_UINT32:
90 if (size_in >= 0 && (gsize)size_in <= G_MAXUINT32) {
91 arg_out->v_uint32 = (guint32)size_in;
97 case GI_TYPE_TAG_INT64:
98 arg_out->v_int64 = size_in;
101 case GI_TYPE_TAG_UINT64:
103 arg_out->v_uint64 = size_in;
109 case GI_TYPE_TAG_FLOAT:
110 case GI_TYPE_TAG_DOUBLE:
111 case GI_TYPE_TAG_GTYPE:
112 case GI_TYPE_TAG_UTF8:
113 case GI_TYPE_TAG_FILENAME:
114 case GI_TYPE_TAG_ARRAY:
115 case GI_TYPE_TAG_INTERFACE:
116 case GI_TYPE_TAG_GLIST:
117 case GI_TYPE_TAG_GSLIST:
118 case GI_TYPE_TAG_GHASH:
119 case GI_TYPE_TAG_ERROR:
120 case GI_TYPE_TAG_UNICHAR:
126 PyErr_Format (PyExc_OverflowError,
127 "Unable to marshal C Py_ssize_t %zd to %s",
129 g_type_tag_to_string (type_tag));
133 PyErr_Format (PyExc_TypeError,
134 "Unable to marshal C Py_ssize_t %zd to %s",
136 g_type_tag_to_string (type_tag));
141 gi_argument_to_gsize (GIArgument *arg_in,
146 case GI_TYPE_TAG_INT8:
147 *gsize_out = arg_in->v_int8;
149 case GI_TYPE_TAG_UINT8:
150 *gsize_out = arg_in->v_uint8;
152 case GI_TYPE_TAG_INT16:
153 *gsize_out = arg_in->v_int16;
155 case GI_TYPE_TAG_UINT16:
156 *gsize_out = arg_in->v_uint16;
158 case GI_TYPE_TAG_INT32:
159 *gsize_out = arg_in->v_int32;
161 case GI_TYPE_TAG_UINT32:
162 *gsize_out = arg_in->v_uint32;
164 case GI_TYPE_TAG_INT64:
165 if (arg_in->v_uint64 > G_MAXSIZE) {
166 PyErr_Format (PyExc_TypeError,
167 "Unable to marshal %s to gsize",
168 g_type_tag_to_string (type_tag));
171 *gsize_out = (gsize)arg_in->v_int64;
173 case GI_TYPE_TAG_UINT64:
174 if (arg_in->v_uint64 > G_MAXSIZE) {
175 PyErr_Format (PyExc_TypeError,
176 "Unable to marshal %s to gsize",
177 g_type_tag_to_string (type_tag));
180 *gsize_out = (gsize)arg_in->v_uint64;
183 PyErr_Format (PyExc_TypeError,
184 "Unable to marshal %s to gsize",
185 g_type_tag_to_string (type_tag));
191 _pygi_marshal_from_py_array (PyGIInvokeState *state,
192 PyGICallableCache *callable_cache,
193 PyGIArgCache *arg_cache,
196 gpointer *cleanup_data)
198 PyGIMarshalFromPyFunc from_py_marshaller;
200 gsize success_count = 0;
201 Py_ssize_t py_length;
204 gboolean is_ptr_array;
205 GArray *array_ = NULL;
206 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
207 PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
208 GITransfer cleanup_transfer = arg_cache->transfer;
211 if (py_arg == Py_None) {
212 arg->v_pointer = NULL;
216 if (!PySequence_Check (py_arg)) {
217 PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
218 Py_TYPE (py_arg)->tp_name);
222 py_length = PySequence_Length (py_arg);
226 if (!pygi_guint_from_pyssize (py_length, &length))
229 if (array_cache->fixed_size >= 0 &&
230 (guint)array_cache->fixed_size != length) {
231 PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %u",
232 array_cache->fixed_size, length);
237 item_size = (guint)array_cache->item_size;
238 is_ptr_array = (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
240 array_ = (GArray *)g_ptr_array_sized_new (length);
242 array_ = g_array_sized_new (array_cache->is_zero_terminated,
248 if (array_ == NULL) {
253 if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8 &&
254 PYGLIB_PyBytes_Check (py_arg)) {
255 gchar *data = PYGLIB_PyBytes_AsString (py_arg);
257 /* Avoid making a copy if the data
258 * is not transferred to the C function
259 * and cannot not be modified by it.
261 if (array_cache->array_type == GI_ARRAY_TYPE_C &&
262 arg_cache->transfer == GI_TRANSFER_NOTHING &&
263 !array_cache->is_zero_terminated) {
264 g_free (array_->data);
266 cleanup_transfer = GI_TRANSFER_EVERYTHING;
268 memcpy (array_->data, data, length);
270 array_->len = length;
271 if (array_cache->is_zero_terminated) {
272 /* If array_ has been created with zero_termination, space for the
273 * terminator is properly allocated, so we're not off-by-one here. */
274 array_->data[length] = '\0';
279 from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
280 for (i = 0, success_count = 0; i < length; i++) {
281 GIArgument item = {0};
282 gpointer item_cleanup_data = NULL;
283 PyObject *py_item = PySequence_GetItem (py_arg, i);
287 if (!from_py_marshaller ( state,
289 sequence_cache->item_cache,
292 &item_cleanup_data)) {
298 if (item_cleanup_data != NULL && item_cleanup_data != item.v_pointer) {
299 /* We only support one level of data discrepancy between an items
300 * data and its cleanup data. This is because we only track a single
301 * extra cleanup data pointer per-argument and cannot track the entire
302 * array of items differing data and cleanup_data.
303 * For example, this would fail if trying to marshal an array of
304 * callback closures marked with SCOPE call type where the cleanup data
305 * is different from the items v_pointer, likewise an array of arrays.
307 PyErr_SetString(PyExc_RuntimeError, "Cannot cleanup item data for array due to "
308 "the items data its cleanup data being different.");
312 /* FIXME: it is much more efficent to have seperate marshaller
313 * for ptr arrays than doing the evaluation
314 * and casting each loop iteration
317 g_ptr_array_add((GPtrArray *)array_, item.v_pointer);
318 } else if (sequence_cache->item_cache->is_pointer) {
319 /* if the item is a pointer, simply copy the pointer */
320 g_assert (item_size == sizeof (item.v_pointer));
321 g_array_insert_val (array_, i, item);
322 } else if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
323 /* Special case handling of flat arrays of gvalue/boxed/struct */
324 PyGIInterfaceCache *item_iface_cache = (PyGIInterfaceCache *) sequence_cache->item_cache;
325 GIBaseInfo *base_info = (GIBaseInfo *) item_iface_cache->interface_info;
326 GIInfoType info_type = g_base_info_get_type (base_info);
329 case GI_INFO_TYPE_UNION:
330 case GI_INFO_TYPE_STRUCT:
332 PyGIArgCache *item_arg_cache = (PyGIArgCache *)item_iface_cache;
333 PyGIMarshalCleanupFunc from_py_cleanup = item_arg_cache->from_py_cleanup;
335 if (g_type_is_a (item_iface_cache->g_type, G_TYPE_VALUE)) {
336 /* Special case GValue flat arrays to properly init and copy the contents. */
337 GValue* dest = (GValue*)(void*)(array_->data + (i * item_size));
338 if (item.v_pointer != NULL) {
339 memset (dest, 0, item_size);
340 g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
341 g_value_copy ((GValue*) item.v_pointer, dest);
343 /* Manually increment the length because we are manually setting the memory. */
347 /* Handles flat arrays of boxed or struct types. */
348 g_array_insert_vals (array_, i, item.v_pointer, 1);
351 /* Cleanup any memory left by the per-item marshaler because
352 * _pygi_marshal_cleanup_from_py_array will not know about this
353 * due to "item" being a temporarily marshaled value done on the stack.
356 from_py_cleanup (state, item_arg_cache, py_item, item_cleanup_data, TRUE);
361 g_array_insert_val (array_, i, item);
364 /* default value copy of a simple type */
365 g_array_insert_val (array_, i, item);
373 if (sequence_cache->item_cache->from_py_cleanup != NULL) {
375 PyGIMarshalCleanupFunc cleanup_func =
376 sequence_cache->item_cache->from_py_cleanup;
378 /* Only attempt per item cleanup on pointer items */
379 if (sequence_cache->item_cache->is_pointer) {
380 for(j = 0; j < success_count; j++) {
381 PyObject *py_seq_item = PySequence_GetItem (py_arg, j);
383 sequence_cache->item_cache,
386 g_ptr_array_index ((GPtrArray *)array_, j) :
387 g_array_index (array_, gpointer, j),
389 Py_DECREF (py_seq_item);
395 g_ptr_array_free ( ( GPtrArray *)array_, TRUE);
397 g_array_free (array_, TRUE);
398 _PyGI_ERROR_PREFIX ("Item %u: ", i);
402 if (array_cache->len_arg_index >= 0) {
403 /* we have an child arg to handle */
404 PyGIArgCache *child_cache =
405 _pygi_callable_cache_get_arg (callable_cache, (guint)array_cache->len_arg_index);
407 if (!gi_argument_from_py_ssize_t (&state->args[child_cache->c_arg_index].arg_value,
409 child_cache->type_tag)) {
414 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
415 /* In the case of GI_ARRAY_C, we give the data directly as the argument
416 * but keep the array_ wrapper as cleanup data so we don't have to find
419 arg->v_pointer = array_->data;
421 if (cleanup_transfer == GI_TRANSFER_EVERYTHING) {
422 g_array_free (array_, FALSE);
423 *cleanup_data = NULL;
425 *cleanup_data = array_;
428 arg->v_pointer = array_;
430 if (cleanup_transfer == GI_TRANSFER_NOTHING) {
431 /* Free everything in cleanup. */
432 *cleanup_data = array_;
433 } else if (cleanup_transfer == GI_TRANSFER_CONTAINER) {
434 /* Make a shallow copy so we can free the elements later in cleanup
435 * because it is possible invoke will free the list before our cleanup. */
436 *cleanup_data = is_ptr_array ?
437 (gpointer)g_ptr_array_ref ((GPtrArray *)array_) :
438 (gpointer)g_array_ref (array_);
439 } else { /* GI_TRANSFER_EVERYTHING */
440 /* No cleanup, everything is given to the callee. */
441 *cleanup_data = NULL;
449 _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
450 PyGIArgCache *arg_cache,
453 gboolean was_processed)
456 GArray *array_ = NULL;
457 GPtrArray *ptr_array_ = NULL;
458 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
459 PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
461 if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
462 ptr_array_ = (GPtrArray *) data;
464 array_ = (GArray *) data;
467 /* clean up items first */
468 if (sequence_cache->item_cache->from_py_cleanup != NULL) {
471 PyGIMarshalCleanupFunc cleanup_func =
472 sequence_cache->item_cache->from_py_cleanup;
474 g_assert (array_ || ptr_array_);
475 len = (array_ != NULL) ? array_->len : ptr_array_->len;
477 for (i = 0; i < len; i++) {
479 PyObject *py_item = NULL;
481 /* case 1: GPtrArray */
482 if (ptr_array_ != NULL)
483 item = g_ptr_array_index (ptr_array_, i);
484 /* case 2: C array or GArray with object pointers */
485 else if (sequence_cache->item_cache->is_pointer)
486 item = g_array_index (array_, gpointer, i);
487 /* case 3: C array or GArray with simple types or structs */
489 item = array_->data + i * array_cache->item_size;
490 /* special-case hack: GValue array items do not get slice
491 * allocated in _pygi_marshal_from_py_array(), so we must
492 * not try to deallocate it as a slice and thus
493 * short-circuit cleanup_func. */
494 if (cleanup_func == pygi_arg_gvalue_from_py_cleanup) {
495 g_value_unset ((GValue*) item);
500 py_item = PySequence_GetItem (py_arg, i);
501 cleanup_func (state, sequence_cache->item_cache, py_item, item, TRUE);
502 Py_XDECREF (py_item);
506 /* Only free the array when we didn't transfer ownership */
507 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
508 /* always free the GArray wrapper created in from_py marshaling and
509 * passed back as cleanup_data
511 g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING);
514 g_array_unref (array_);
516 g_ptr_array_unref (ptr_array_);
525 _pygi_marshal_to_py_array (PyGIInvokeState *state,
526 PyGICallableCache *callable_cache,
527 PyGIArgCache *arg_cache,
529 gpointer *cleanup_data)
532 PyObject *py_obj = NULL;
533 PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
534 PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
535 guint processed_items = 0;
537 /* GArrays make it easier to iterate over arrays
538 * with different element sizes but requires that
539 * we allocate a GArray if the argument was a C array
541 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
543 if (array_cache->fixed_size >= 0) {
544 g_assert(arg->v_pointer != NULL);
545 len = array_cache->fixed_size;
546 } else if (array_cache->is_zero_terminated) {
547 if (arg->v_pointer == NULL) {
549 } else if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
550 len = strlen (arg->v_pointer);
552 len = g_strv_length ((gchar **)arg->v_pointer);
555 GIArgument *len_arg = &state->args[array_cache->len_arg_index].arg_value;
556 PyGIArgCache *sub_cache = _pygi_callable_cache_get_arg (callable_cache,
557 (guint)array_cache->len_arg_index);
559 if (!gi_argument_to_gsize (len_arg, &len, sub_cache->type_tag)) {
564 array_ = g_array_new (FALSE,
566 (guint)array_cache->item_size);
567 if (array_ == NULL) {
570 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && arg->v_pointer != NULL)
571 g_free (arg->v_pointer);
576 if (array_->data != NULL)
577 g_free (array_->data);
578 array_->data = arg->v_pointer;
579 array_->len = (guint)len;
581 array_ = arg->v_pointer;
584 if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
585 if (arg->v_pointer == NULL) {
586 py_obj = PYGLIB_PyBytes_FromString ("");
588 py_obj = PYGLIB_PyBytes_FromStringAndSize (array_->data, array_->len);
591 if (arg->v_pointer == NULL) {
592 py_obj = PyList_New (0);
597 PyGIMarshalToPyFunc item_to_py_marshaller;
598 PyGIArgCache *item_arg_cache;
599 GPtrArray *item_cleanups;
601 py_obj = PyList_New (array_->len);
605 item_cleanups = g_ptr_array_sized_new (array_->len);
606 *cleanup_data = item_cleanups;
608 item_arg_cache = seq_cache->item_cache;
609 item_to_py_marshaller = item_arg_cache->to_py_marshaller;
611 item_size = g_array_get_element_size (array_);
613 for (i = 0; i < array_->len; i++) {
614 GIArgument item_arg = {0};
616 gpointer item_cleanup_data = NULL;
618 /* If we are receiving an array of pointers, simply assign the pointer
619 * and move on, letting the per-item marshaler deal with the
620 * various transfer modes and ref counts (e.g. g_variant_ref_sink).
622 if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
623 item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
625 } else if (item_arg_cache->is_pointer) {
626 item_arg.v_pointer = g_array_index (array_, gpointer, i);
628 } else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
629 PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *) item_arg_cache;
631 /* FIXME: This probably doesn't work with boxed types or gvalues.
632 * See fx. _pygi_marshal_from_py_array() */
633 switch (g_base_info_get_type (iface_cache->interface_info)) {
634 case GI_INFO_TYPE_STRUCT:
635 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING &&
636 !g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
637 /* array elements are structs */
638 gpointer *_struct = g_malloc (item_size);
639 memcpy (_struct, array_->data + i * item_size,
641 item_arg.v_pointer = _struct;
643 item_arg.v_pointer = array_->data + i * item_size;
646 case GI_INFO_TYPE_ENUM:
647 memcpy (&item_arg, array_->data + i * item_size, item_size);
650 item_arg.v_pointer = g_array_index (array_, gpointer, i);
654 memcpy (&item_arg, array_->data + i * item_size, item_size);
657 py_item = item_to_py_marshaller ( state,
663 g_ptr_array_index (item_cleanups, i) = item_cleanup_data;
665 if (py_item == NULL) {
668 if (array_cache->array_type == GI_ARRAY_TYPE_C)
669 g_array_unref (array_);
671 g_ptr_array_unref (item_cleanups);
675 PyList_SET_ITEM (py_obj, i, py_item);
681 if (array_cache->array_type == GI_ARRAY_TYPE_C)
682 g_array_free (array_, FALSE);
687 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
688 g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING);
690 /* clean up unprocessed items */
691 if (seq_cache->item_cache->to_py_cleanup != NULL) {
693 PyGIMarshalToPyCleanupFunc cleanup_func = seq_cache->item_cache->to_py_cleanup;
694 for (j = processed_items; j < array_->len; j++) {
696 seq_cache->item_cache,
698 g_array_index (array_, gpointer, j),
703 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
704 g_array_free (array_, TRUE);
711 _wrap_c_array (PyGIInvokeState *state,
712 PyGIArgGArray *array_cache,
718 if (array_cache->fixed_size >= 0) {
719 len = array_cache->fixed_size;
720 } else if (array_cache->is_zero_terminated) {
721 len = g_strv_length ((gchar **)data);
722 } else if (array_cache->len_arg_index >= 0) {
723 GIArgument *len_arg = &state->args[array_cache->len_arg_index].arg_value;
724 len = len_arg->v_long;
727 array_ = g_array_new (FALSE,
729 (guint)array_cache->item_size);
734 g_free (array_->data);
736 array_->len = (guint)len;
742 _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
743 PyGIArgCache *arg_cache,
744 gpointer cleanup_data,
746 gboolean was_processed)
748 GArray *array_ = NULL;
749 GPtrArray *ptr_array_ = NULL;
750 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
751 PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
752 gboolean free_array = FALSE;
753 gboolean free_array_full = TRUE;
755 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
756 arg_cache->transfer == GI_TRANSFER_CONTAINER) {
760 /* If this isn't a garray create one to help process variable sized
762 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
763 array_ = _wrap_c_array (state, array_cache, data);
769 free_array_full = arg_cache->transfer != GI_TRANSFER_NOTHING;
770 } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
771 ptr_array_ = (GPtrArray *) data;
773 array_ = (GArray *) data;
776 if (sequence_cache->item_cache->to_py_cleanup != NULL) {
777 GPtrArray *item_cleanups = (GPtrArray *) cleanup_data;
780 PyGIMarshalToPyCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
782 g_assert (array_ || ptr_array_);
783 len = (array_ != NULL) ? array_->len : ptr_array_->len;
785 for (i = 0; i < len; i++) {
787 sequence_cache->item_cache,
788 g_ptr_array_index(item_cleanups, i),
789 (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
795 g_ptr_array_unref ((GPtrArray *) cleanup_data);
799 g_array_free (array_, free_array_full);
801 g_ptr_array_free (ptr_array_, free_array_full);
806 _array_cache_free_func (PyGIArgGArray *cache)
809 pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache);
810 g_slice_free (PyGIArgGArray, cache);
815 pygi_arg_garray_len_arg_setup (PyGIArgCache *arg_cache,
816 GITypeInfo *type_info,
817 PyGICallableCache *callable_cache,
818 PyGIDirection direction,
820 gssize *py_arg_index)
822 PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
824 /* attempt len_arg_index setup for the first time */
825 if (seq_cache->len_arg_index < 0) {
826 seq_cache->len_arg_index = g_type_info_get_array_length (type_info);
828 /* offset by self arg for methods and vfuncs */
829 if (seq_cache->len_arg_index >= 0 && callable_cache != NULL) {
830 seq_cache->len_arg_index += callable_cache->args_offset;
834 if (seq_cache->len_arg_index >= 0) {
835 PyGIArgCache *child_cache = NULL;
837 child_cache = _pygi_callable_cache_get_arg (callable_cache,
838 (guint)seq_cache->len_arg_index);
839 if (child_cache == NULL) {
840 child_cache = pygi_arg_cache_alloc ();
842 /* If the "length" arg cache already exists (the length comes before
843 * the array in the argument list), remove it from the to_py_args list
844 * because it does not belong in "to python" return tuple. The length
845 * will implicitly be a part of the returned Python list.
847 if (direction & PYGI_DIRECTION_TO_PYTHON) {
848 callable_cache->to_py_args =
849 g_slist_remove (callable_cache->to_py_args, child_cache);
852 /* This is a case where the arg cache already exists and has been
853 * setup by another array argument sharing the same length argument.
854 * See: gi_marshalling_tests_multi_array_key_value_in
856 if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
860 /* There is a length argument for this array, so increment the number
861 * of "to python" child arguments when applicable.
863 if (direction & PYGI_DIRECTION_TO_PYTHON)
864 callable_cache->n_to_py_child_args++;
866 child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
867 child_cache->direction = direction;
868 child_cache->to_py_marshaller = pygi_marshal_to_py_basic_type_cache_adapter;
869 child_cache->from_py_marshaller = pygi_marshal_from_py_basic_type_cache_adapter;
870 child_cache->py_arg_index = -1;
872 /* ugly edge case code:
874 * When the length comes before the array parameter we need to update
875 * indexes of arguments after the index argument.
877 if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
879 (*py_arg_index) -= 1;
880 callable_cache->n_py_args -= 1;
882 for (i = (guint)seq_cache->len_arg_index + 1;
883 (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) {
884 PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
885 if (update_cache == NULL)
888 update_cache->py_arg_index -= 1;
892 _pygi_callable_cache_set_arg (callable_cache, (guint)seq_cache->len_arg_index, child_cache);
900 pygi_arg_garray_setup (PyGIArgGArray *sc,
901 GITypeInfo *type_info,
902 GIArgInfo *arg_info, /* may be NULL for return arguments */
904 PyGIDirection direction,
905 PyGICallableCache *callable_cache)
907 GITypeInfo *item_type_info;
908 PyGIArgCache *arg_cache = (PyGIArgCache *)sc;
910 if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc,
919 ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func;
920 sc->array_type = g_type_info_get_array_type (type_info);
921 sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
922 sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
923 sc->len_arg_index = -1; /* setup by pygi_arg_garray_len_arg_setup */
925 item_type_info = g_type_info_get_param_type (type_info, 0);
926 sc->item_size = _pygi_g_type_info_size (item_type_info);
927 g_base_info_unref ( (GIBaseInfo *)item_type_info);
929 if (direction & PYGI_DIRECTION_FROM_PYTHON) {
930 arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
931 arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
934 if (direction & PYGI_DIRECTION_TO_PYTHON) {
935 arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
936 arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
943 pygi_arg_garray_new_from_info (GITypeInfo *type_info,
946 PyGIDirection direction,
947 PyGICallableCache *callable_cache)
949 PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray);
950 if (array_cache == NULL)
953 if (!pygi_arg_garray_setup (array_cache,
959 pygi_arg_cache_free ( (PyGIArgCache *)array_cache);
963 return (PyGIArgCache *)array_cache;