#include <Python.h>
#include <glib.h>
-#include <pyglib-python-compat.h>
+#include "pygi-python-compat.h"
#include "pygi-array.h"
#include "pygi-info.h"
#include "pygi-marshal-cleanup.h"
case GI_TYPE_TAG_INT8:
if (size_in >= G_MININT8 && size_in <= G_MAXINT8) {
- arg_out->v_int8 = size_in;
+ arg_out->v_int8 = (gint8)size_in;
return TRUE;
} else {
goto overflow;
case GI_TYPE_TAG_UINT8:
if (size_in >= 0 && size_in <= G_MAXUINT8) {
- arg_out->v_uint8 = size_in;
+ arg_out->v_uint8 = (guint8)size_in;
return TRUE;
} else {
goto overflow;
case GI_TYPE_TAG_INT16:
if (size_in >= G_MININT16 && size_in <= G_MAXINT16) {
- arg_out->v_int16 = size_in;
+ arg_out->v_int16 = (gint16)size_in;
return TRUE;
} else {
goto overflow;
case GI_TYPE_TAG_UINT16:
if (size_in >= 0 && size_in <= G_MAXUINT16) {
- arg_out->v_uint16 = size_in;
+ arg_out->v_uint16 = (guint16)size_in;
return TRUE;
} else {
goto overflow;
/* Ranges assume two's complement */
case GI_TYPE_TAG_INT32:
if (size_in >= G_MININT32 && size_in <= G_MAXINT32) {
- arg_out->v_int32 = size_in;
+ arg_out->v_int32 = (gint32)size_in;
return TRUE;
} else {
goto overflow;
}
case GI_TYPE_TAG_UINT32:
- if (size_in >= 0 && size_in <= G_MAXUINT32) {
- arg_out->v_uint32 = size_in;
+ if (size_in >= 0 && (gsize)size_in <= G_MAXUINT32) {
+ arg_out->v_uint32 = (guint32)size_in;
return TRUE;
} else {
goto overflow;
*gsize_out = arg_in->v_uint32;
return TRUE;
case GI_TYPE_TAG_INT64:
- *gsize_out = arg_in->v_int64;
+ if (arg_in->v_uint64 > G_MAXSIZE) {
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to gsize",
+ g_type_tag_to_string (type_tag));
+ return FALSE;
+ }
+ *gsize_out = (gsize)arg_in->v_int64;
return TRUE;
case GI_TYPE_TAG_UINT64:
- *gsize_out = arg_in->v_uint64;
+ if (arg_in->v_uint64 > G_MAXSIZE) {
+ PyErr_Format (PyExc_TypeError,
+ "Unable to marshal %s to gsize",
+ g_type_tag_to_string (type_tag));
+ return FALSE;
+ }
+ *gsize_out = (gsize)arg_in->v_uint64;
return TRUE;
default:
PyErr_Format (PyExc_TypeError,
gpointer *cleanup_data)
{
PyGIMarshalFromPyFunc from_py_marshaller;
- int i = 0;
- int success_count = 0;
- Py_ssize_t length;
- gssize item_size;
+ guint i = 0;
+ gsize success_count = 0;
+ Py_ssize_t py_length;
+ guint length;
+ guint item_size;
gboolean is_ptr_array;
GArray *array_ = NULL;
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
if (!PySequence_Check (py_arg)) {
PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
- py_arg->ob_type->tp_name);
+ Py_TYPE (py_arg)->tp_name);
return FALSE;
}
- length = PySequence_Length (py_arg);
- if (length < 0)
+ py_length = PySequence_Length (py_arg);
+ if (py_length < 0)
+ return FALSE;
+
+ if (!pygi_guint_from_pyssize (py_length, &length))
return FALSE;
if (array_cache->fixed_size >= 0 &&
- array_cache->fixed_size != length) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
+ (guint)array_cache->fixed_size != length) {
+ PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %u",
array_cache->fixed_size, length);
return FALSE;
}
- item_size = array_cache->item_size;
+ item_size = (guint)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);
if (g_type_is_a (item_iface_cache->g_type, G_TYPE_VALUE)) {
/* Special case GValue flat arrays to properly init and copy the contents. */
- GValue* dest = (GValue*) (array_->data + (i * item_size));
+ GValue* dest = (GValue*)(void*)(array_->data + (i * item_size));
if (item.v_pointer != NULL) {
memset (dest, 0, item_size);
g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
}
success_count++;
- continue;
-err:
- if (sequence_cache->item_cache->from_py_cleanup != NULL) {
- gsize j;
- PyGIMarshalCleanupFunc cleanup_func =
- sequence_cache->item_cache->from_py_cleanup;
+ }
+ goto array_success;
- /* Only attempt per item cleanup on pointer items */
- if (sequence_cache->item_cache->is_pointer) {
- for(j = 0; j < success_count; j++) {
- PyObject *py_item = PySequence_GetItem (py_arg, j);
- cleanup_func (state,
- sequence_cache->item_cache,
- py_item,
- is_ptr_array ?
- g_ptr_array_index ((GPtrArray *)array_, j) :
- g_array_index (array_, gpointer, j),
- TRUE);
- Py_DECREF (py_item);
- }
+err:
+ if (sequence_cache->item_cache->from_py_cleanup != NULL) {
+ gsize j;
+ PyGIMarshalCleanupFunc cleanup_func =
+ sequence_cache->item_cache->from_py_cleanup;
+
+ /* Only attempt per item cleanup on pointer items */
+ if (sequence_cache->item_cache->is_pointer) {
+ for(j = 0; j < success_count; j++) {
+ PyObject *py_seq_item = PySequence_GetItem (py_arg, j);
+ cleanup_func (state,
+ sequence_cache->item_cache,
+ py_seq_item,
+ is_ptr_array ?
+ g_ptr_array_index ((GPtrArray *)array_, j) :
+ g_array_index (array_, gpointer, j),
+ TRUE);
+ Py_DECREF (py_seq_item);
}
}
-
- if (is_ptr_array)
- g_ptr_array_free ( ( GPtrArray *)array_, TRUE);
- else
- g_array_free (array_, TRUE);
- _PyGI_ERROR_PREFIX ("Item %i: ", i);
- return FALSE;
}
+ if (is_ptr_array)
+ g_ptr_array_free ( ( GPtrArray *)array_, TRUE);
+ else
+ g_array_free (array_, TRUE);
+ _PyGI_ERROR_PREFIX ("Item %u: ", i);
+ return FALSE;
+
array_success:
if (array_cache->len_arg_index >= 0) {
/* we have an child arg to handle */
PyGIArgCache *child_cache =
- _pygi_callable_cache_get_arg (callable_cache, array_cache->len_arg_index);
+ _pygi_callable_cache_get_arg (callable_cache, (guint)array_cache->len_arg_index);
if (!gi_argument_from_py_ssize_t (&state->args[child_cache->c_arg_index].arg_value,
length,
/* clean up items first */
if (sequence_cache->item_cache->from_py_cleanup != NULL) {
gsize i;
- guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
+ guint len;
PyGIMarshalCleanupFunc cleanup_func =
sequence_cache->item_cache->from_py_cleanup;
+ g_assert (array_ || ptr_array_);
+ len = (array_ != NULL) ? array_->len : ptr_array_->len;
+
for (i = 0; i < len; i++) {
gpointer item;
PyObject *py_item = NULL;
_pygi_marshal_to_py_array (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
GArray *array_;
PyObject *py_obj = NULL;
PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
- gsize processed_items = 0;
+ guint processed_items = 0;
/* GArrays make it easier to iterate over arrays
* with different element sizes but requires that
}
} else {
GIArgument *len_arg = &state->args[array_cache->len_arg_index].arg_value;
- PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache,
- array_cache->len_arg_index);
+ PyGIArgCache *sub_cache = _pygi_callable_cache_get_arg (callable_cache,
+ (guint)array_cache->len_arg_index);
- if (!gi_argument_to_gsize (len_arg, &len, arg_cache->type_tag)) {
+ if (!gi_argument_to_gsize (len_arg, &len, sub_cache->type_tag)) {
return NULL;
}
}
array_ = g_array_new (FALSE,
FALSE,
- array_cache->item_size);
+ (guint)array_cache->item_size);
if (array_ == NULL) {
PyErr_NoMemory ();
if (array_->data != NULL)
g_free (array_->data);
array_->data = arg->v_pointer;
- array_->len = len;
+ array_->len = (guint)len;
} else {
array_ = arg->v_pointer;
}
if (arg->v_pointer == NULL) {
py_obj = PyList_New (0);
} else {
- int i;
+ guint i;
gsize item_size;
PyGIMarshalToPyFunc item_to_py_marshaller;
PyGIArgCache *item_arg_cache;
+ GPtrArray *item_cleanups;
py_obj = PyList_New (array_->len);
if (py_obj == NULL)
goto err;
+ item_cleanups = g_ptr_array_sized_new (array_->len);
+ *cleanup_data = item_cleanups;
item_arg_cache = seq_cache->item_cache;
item_to_py_marshaller = item_arg_cache->to_py_marshaller;
for (i = 0; i < array_->len; i++) {
GIArgument item_arg = {0};
PyObject *py_item;
+ gpointer item_cleanup_data = NULL;
/* If we are receiving an array of pointers, simply assign the pointer
* and move on, letting the per-item marshaler deal with the
item_arg.v_pointer = array_->data + i * item_size;
}
break;
+ case GI_INFO_TYPE_ENUM:
+ memcpy (&item_arg, array_->data + i * item_size, item_size);
+ break;
default:
item_arg.v_pointer = g_array_index (array_, gpointer, i);
break;
py_item = item_to_py_marshaller ( state,
callable_cache,
item_arg_cache,
- &item_arg);
+ &item_arg,
+ &item_cleanup_data);
+
+ g_ptr_array_index (item_cleanups, i) = item_cleanup_data;
if (py_item == NULL) {
Py_CLEAR (py_obj);
if (array_cache->array_type == GI_ARRAY_TYPE_C)
g_array_unref (array_);
+ g_ptr_array_unref (item_cleanups);
+
goto err;
}
PyList_SET_ITEM (py_obj, i, py_item);
} else {
/* clean up unprocessed items */
if (seq_cache->item_cache->to_py_cleanup != NULL) {
- int j;
- PyGIMarshalCleanupFunc cleanup_func = seq_cache->item_cache->to_py_cleanup;
+ guint j;
+ PyGIMarshalToPyCleanupFunc cleanup_func = seq_cache->item_cache->to_py_cleanup;
for (j = processed_items; j < array_->len; j++) {
cleanup_func (state,
seq_cache->item_cache,
array_ = g_array_new (FALSE,
FALSE,
- array_cache->item_size);
+ (guint)array_cache->item_size);
if (array_ == NULL)
return NULL;
g_free (array_->data);
array_->data = data;
- array_->len = len;
+ array_->len = (guint)len;
return array_;
}
static void
_pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
- PyObject *dummy,
+ gpointer cleanup_data,
gpointer data,
gboolean was_processed)
{
+ GArray *array_ = NULL;
+ GPtrArray *ptr_array_ = NULL;
+ PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
+ gboolean free_array = FALSE;
+ gboolean free_array_full = TRUE;
+
if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
arg_cache->transfer == GI_TRANSFER_CONTAINER) {
- GArray *array_ = NULL;
- GPtrArray *ptr_array_ = NULL;
- PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
- PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
+ free_array = TRUE;
+ }
- /* If this isn't a garray create one to help process variable sized
- array elements */
- if (array_cache->array_type == GI_ARRAY_TYPE_C) {
- array_ = _wrap_c_array (state, array_cache, data);
+ /* If this isn't a garray create one to help process variable sized
+ array elements */
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
+ array_ = _wrap_c_array (state, array_cache, data);
- if (array_ == NULL)
- return;
+ if (array_ == NULL)
+ return;
- } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
- ptr_array_ = (GPtrArray *) data;
- } else {
- array_ = (GArray *) data;
- }
-
- if (sequence_cache->item_cache->to_py_cleanup != NULL) {
- gsize i;
- guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
+ free_array = TRUE;
+ free_array_full = arg_cache->transfer != GI_TRANSFER_NOTHING;
+ } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ ptr_array_ = (GPtrArray *) data;
+ } else {
+ array_ = (GArray *) data;
+ }
- PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
- for (i = 0; i < len; i++) {
- cleanup_func (state,
- sequence_cache->item_cache,
- NULL,
- (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
- was_processed);
- }
+ if (sequence_cache->item_cache->to_py_cleanup != NULL) {
+ GPtrArray *item_cleanups = (GPtrArray *) cleanup_data;
+ gsize i;
+ guint len;
+ PyGIMarshalToPyCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
+
+ g_assert (array_ || ptr_array_);
+ len = (array_ != NULL) ? array_->len : ptr_array_->len;
+
+ for (i = 0; i < len; i++) {
+ cleanup_func (state,
+ sequence_cache->item_cache,
+ g_ptr_array_index(item_cleanups, i),
+ (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
+ was_processed);
}
+ }
+
+ if (cleanup_data)
+ g_ptr_array_unref ((GPtrArray *) cleanup_data);
+ if (free_array) {
if (array_ != NULL)
- g_array_free (array_, TRUE);
+ g_array_free (array_, free_array_full);
else
- g_ptr_array_free (ptr_array_, TRUE);
+ g_ptr_array_free (ptr_array_, free_array_full);
}
}
PyGIArgCache *child_cache = NULL;
child_cache = _pygi_callable_cache_get_arg (callable_cache,
- seq_cache->len_arg_index);
+ (guint)seq_cache->len_arg_index);
if (child_cache == NULL) {
child_cache = pygi_arg_cache_alloc ();
} else {
child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
child_cache->direction = direction;
- child_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
- child_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
+ child_cache->to_py_marshaller = pygi_marshal_to_py_basic_type_cache_adapter;
+ child_cache->from_py_marshaller = pygi_marshal_from_py_basic_type_cache_adapter;
child_cache->py_arg_index = -1;
/* ugly edge case code:
* indexes of arguments after the index argument.
*/
if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
- gssize i;
+ guint i;
(*py_arg_index) -= 1;
callable_cache->n_py_args -= 1;
- for (i = seq_cache->len_arg_index + 1;
- i < _pygi_callable_cache_args_len (callable_cache); i++) {
+ for (i = (guint)seq_cache->len_arg_index + 1;
+ (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) {
PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
if (update_cache == NULL)
break;
}
}
- _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
+ _pygi_callable_cache_set_arg (callable_cache, (guint)seq_cache->len_arg_index, child_cache);
return child_cache;
}