static PyObject * _wrap_g_field_info_set_value (PyGIBaseInfo *self, PyObject *args) { PyObject *instance; PyObject *py_value; GIBaseInfo *container_info; GIInfoType container_info_type; gpointer pointer; GITypeInfo *field_type_info; GIArgument value; PyObject *retval = NULL; if (!PyArg_ParseTuple (args, "OO:FieldInfo.set_value", &instance, &py_value)) { return NULL; } container_info = g_base_info_get_container (self->info); g_assert (container_info != NULL); /* Check the instance. */ if (!_pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) container_info, TRUE, instance)) { _PyGI_ERROR_PREFIX ("argument 1: "); return NULL; } /* Get the pointer to the container. */ container_info_type = g_base_info_get_type (container_info); switch (container_info_type) { case GI_INFO_TYPE_UNION: case GI_INFO_TYPE_STRUCT: pointer = pyg_boxed_get (instance, void); break; case GI_INFO_TYPE_OBJECT: pointer = pygobject_get (instance); break; default: /* Other types don't have fields. */ g_assert_not_reached(); } field_type_info = g_field_info_get_type ( (GIFieldInfo *) self->info); /* Check the value. */ { gboolean retval; retval = _pygi_g_type_info_check_object (field_type_info, py_value, TRUE); if (retval < 0) { goto out; } if (!retval) { _PyGI_ERROR_PREFIX ("argument 2: "); goto out; } } /* Set the field's value. */ /* A few types are not handled by g_field_info_set_field, so do it here. */ if (!g_type_info_is_pointer (field_type_info) && g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) { GIBaseInfo *info; GIInfoType info_type; if (! (g_field_info_get_flags ( (GIFieldInfo *) self->info) & GI_FIELD_IS_WRITABLE)) { PyErr_SetString (PyExc_RuntimeError, "field is not writable"); goto out; } info = g_type_info_get_interface (field_type_info); info_type = g_base_info_get_type (info); switch (info_type) { case GI_INFO_TYPE_UNION: PyErr_SetString (PyExc_NotImplementedError, "setting an union is not supported yet"); goto out; case GI_INFO_TYPE_STRUCT: { gboolean is_simple; gsize offset; gssize size; is_simple = pygi_g_struct_info_is_simple ( (GIStructInfo *) info); if (!is_simple) { PyErr_SetString (PyExc_TypeError, "cannot set a structure which has no well-defined ownership transfer rules"); g_base_info_unref (info); goto out; } value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_NOTHING); if (PyErr_Occurred()) { g_base_info_unref (info); goto out; } offset = g_field_info_get_offset ( (GIFieldInfo *) self->info); size = g_struct_info_get_size ( (GIStructInfo *) info); g_assert (size > 0); g_memmove ((char*) pointer + offset, value.v_pointer, size); g_base_info_unref (info); retval = Py_None; goto out; } default: /* Fallback. */ break; } g_base_info_unref (info); } else if (g_type_info_is_pointer (field_type_info) && g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_VOID) { int offset; if (py_value != Py_None && !PYGLIB_PyLong_Check(py_value)) { if (PyErr_WarnEx(PyExc_RuntimeWarning, "Usage of gpointers to store objects is being deprecated. " "Please use integer values only, see: https://bugzilla.gnome.org/show_bug.cgi?id=683599", 1)) goto out; } offset = g_field_info_get_offset ((GIFieldInfo *) self->info); value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_NOTHING); /* Decrement the previous python object stashed on the void pointer. * This seems somewhat dangerous as the code is blindly assuming any * void pointer field stores a python object pointer and then decrefs it. * This is essentially the same as something like: * Py_XDECREF(struct->void_ptr); */ Py_XDECREF(G_STRUCT_MEMBER (gpointer, pointer, offset)); /* Assign and increment the newly assigned object. At this point the value * arg will hold a pointer the python object "py_value" or NULL. * This is essentially: * struct->void_ptr = value.v_pointer; * Py_XINCREF(struct->void_ptr); */ G_STRUCT_MEMBER (gpointer, pointer, offset) = (gpointer)value.v_pointer; Py_XINCREF(G_STRUCT_MEMBER (gpointer, pointer, offset)); retval = Py_None; goto out; } value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_EVERYTHING); if (PyErr_Occurred()) { goto out; } if (!g_field_info_set_field ( (GIFieldInfo *) self->info, pointer, &value)) { _pygi_argument_release (&value, field_type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); PyErr_SetString (PyExc_RuntimeError, "unable to set value for field"); goto out; } retval = Py_None; out: g_base_info_unref ( (GIBaseInfo *) field_type_info); Py_XINCREF (retval); return retval; }
GIArgument _pygi_argument_from_object (PyObject *object, GITypeInfo *type_info, GITransfer transfer) { GIArgument arg; GITypeTag type_tag; gpointer cleanup_data = NULL; memset(&arg, 0, sizeof(GIArgument)); type_tag = g_type_info_get_tag (type_info); /* Ignores cleanup data for now. */ if (_pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer, &cleanup_data) || PyErr_Occurred()) { return arg; } switch (type_tag) { case GI_TYPE_TAG_ARRAY: { Py_ssize_t length; gboolean is_zero_terminated; GITypeInfo *item_type_info; gsize item_size; GArray *array; GITransfer item_transfer; Py_ssize_t i; if (object == Py_None) { arg.v_pointer = NULL; break; } /* Note, strings are sequences, but we cannot accept them here */ if (!PySequence_Check (object) || #if PY_VERSION_HEX < 0x03000000 PyString_Check (object) || #endif PyUnicode_Check (object)) { PyErr_SetString (PyExc_TypeError, "expected sequence"); break; } length = PySequence_Length (object); if (length < 0) { break; } is_zero_terminated = g_type_info_is_zero_terminated (type_info); item_type_info = g_type_info_get_param_type (type_info, 0); /* we handle arrays that are really strings specially, see below */ if (g_type_info_get_tag (item_type_info) == GI_TYPE_TAG_UINT8) item_size = 1; else item_size = sizeof (GIArgument); array = g_array_sized_new (is_zero_terminated, FALSE, item_size, length); if (array == NULL) { g_base_info_unref ( (GIBaseInfo *) item_type_info); PyErr_NoMemory(); break; } if (g_type_info_get_tag (item_type_info) == GI_TYPE_TAG_UINT8 && PYGLIB_PyBytes_Check(object)) { memcpy(array->data, PYGLIB_PyBytes_AsString(object), length); array->len = length; goto array_success; } item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; for (i = 0; i < length; i++) { PyObject *py_item; GIArgument item; py_item = PySequence_GetItem (object, i); if (py_item == NULL) { goto array_item_error; } item = _pygi_argument_from_object (py_item, item_type_info, item_transfer); Py_DECREF (py_item); if (PyErr_Occurred()) { goto array_item_error; } g_array_insert_val (array, i, item); continue; array_item_error: /* Free everything we have converted so far. */ _pygi_argument_release ( (GIArgument *) &array, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); array = NULL; _PyGI_ERROR_PREFIX ("Item %zd: ", i); break; } array_success: arg.v_pointer = array; g_base_info_unref ( (GIBaseInfo *) item_type_info); break; } case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; GIInfoType info_type; info = g_type_info_get_interface (type_info); info_type = g_base_info_get_type (info); switch (info_type) { case GI_INFO_TYPE_CALLBACK: /* This should be handled in invoke() */ g_assert_not_reached(); break; case GI_INFO_TYPE_BOXED: case GI_INFO_TYPE_STRUCT: case GI_INFO_TYPE_UNION: { GType g_type; PyObject *py_type; gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) && (g_struct_info_is_foreign ((GIStructInfo *) info)); g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) info); /* Note for G_TYPE_VALUE g_type: * This will currently leak the GValue that is allocated and * stashed in arg.v_pointer. Out argument marshaling for caller * allocated GValues already pass in memory for the GValue. * Further re-factoring is needed to fix this leak. * See: https://bugzilla.gnome.org/show_bug.cgi?id=693405 */ pygi_arg_struct_from_py_marshal (object, &arg, NULL, /*arg_name*/ info, /*interface_info*/ g_type, py_type, transfer, FALSE, /*copy_reference*/ is_foreign, g_type_info_is_pointer (type_info)); Py_DECREF (py_type); break; } case GI_INFO_TYPE_ENUM: case GI_INFO_TYPE_FLAGS: { PyObject *int_; int_ = PYGLIB_PyNumber_Long (object); if (int_ == NULL) { break; } arg.v_int = PYGLIB_PyLong_AsLong (int_); Py_DECREF (int_); break; } case GI_INFO_TYPE_INTERFACE: case GI_INFO_TYPE_OBJECT: /* An error within this call will result in a NULL arg */ pygi_arg_gobject_out_arg_from_py (object, &arg, transfer); break; default: g_assert_not_reached(); } g_base_info_unref (info); break; } case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: { Py_ssize_t length; GITypeInfo *item_type_info; GSList *list = NULL; GITransfer item_transfer; Py_ssize_t i; if (object == Py_None) { arg.v_pointer = NULL; break; } length = PySequence_Length (object); if (length < 0) { break; } item_type_info = g_type_info_get_param_type (type_info, 0); g_assert (item_type_info != NULL); item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; for (i = length - 1; i >= 0; i--) { PyObject *py_item; GIArgument item; py_item = PySequence_GetItem (object, i); if (py_item == NULL) { goto list_item_error; } item = _pygi_argument_from_object (py_item, item_type_info, item_transfer); Py_DECREF (py_item); if (PyErr_Occurred()) { goto list_item_error; } if (type_tag == GI_TYPE_TAG_GLIST) { list = (GSList *) g_list_prepend ( (GList *) list, item.v_pointer); } else { list = g_slist_prepend (list, item.v_pointer); } continue; list_item_error: /* Free everything we have converted so far. */ _pygi_argument_release ( (GIArgument *) &list, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); list = NULL; _PyGI_ERROR_PREFIX ("Item %zd: ", i); break; } arg.v_pointer = list; g_base_info_unref ( (GIBaseInfo *) item_type_info); break; } case GI_TYPE_TAG_GHASH: { Py_ssize_t length; PyObject *keys; PyObject *values; GITypeInfo *key_type_info; GITypeInfo *value_type_info; GITypeTag key_type_tag; GHashFunc hash_func; GEqualFunc equal_func; GHashTable *hash_table; GITransfer item_transfer; Py_ssize_t i; if (object == Py_None) { arg.v_pointer = NULL; break; } length = PyMapping_Length (object); if (length < 0) { break; } keys = PyMapping_Keys (object); if (keys == NULL) { break; } values = PyMapping_Values (object); if (values == NULL) { Py_DECREF (keys); break; } key_type_info = g_type_info_get_param_type (type_info, 0); g_assert (key_type_info != NULL); value_type_info = g_type_info_get_param_type (type_info, 1); g_assert (value_type_info != NULL); key_type_tag = g_type_info_get_tag (key_type_info); switch (key_type_tag) { case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: hash_func = g_str_hash; equal_func = g_str_equal; break; default: hash_func = NULL; equal_func = NULL; } hash_table = g_hash_table_new (hash_func, equal_func); if (hash_table == NULL) { PyErr_NoMemory(); goto hash_table_release; } item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; for (i = 0; i < length; i++) { PyObject *py_key; PyObject *py_value; GIArgument key; GIArgument value; py_key = PyList_GET_ITEM (keys, i); py_value = PyList_GET_ITEM (values, i); key = _pygi_argument_from_object (py_key, key_type_info, item_transfer); if (PyErr_Occurred()) { goto hash_table_item_error; } value = _pygi_argument_from_object (py_value, value_type_info, item_transfer); if (PyErr_Occurred()) { _pygi_argument_release (&key, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); goto hash_table_item_error; } g_hash_table_insert (hash_table, key.v_pointer, _pygi_arg_to_hash_pointer (&value, g_type_info_get_tag (value_type_info))); continue; hash_table_item_error: /* Free everything we have converted so far. */ _pygi_argument_release ( (GIArgument *) &hash_table, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); hash_table = NULL; _PyGI_ERROR_PREFIX ("Item %zd: ", i); break; } arg.v_pointer = hash_table; hash_table_release: g_base_info_unref ( (GIBaseInfo *) key_type_info); g_base_info_unref ( (GIBaseInfo *) value_type_info); Py_DECREF (keys); Py_DECREF (values); break; } case GI_TYPE_TAG_ERROR: PyErr_SetString (PyExc_NotImplementedError, "error marshalling is not supported yet"); /* TODO */ break; default: g_assert_not_reached (); } return arg; }
void _pygi_argument_release (GIArgument *arg, GITypeInfo *type_info, GITransfer transfer, GIDirection direction) { GITypeTag type_tag; gboolean is_out = (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT); type_tag = g_type_info_get_tag (type_info); switch (type_tag) { case GI_TYPE_TAG_VOID: /* Don't do anything, it's transparent to the C side */ break; case GI_TYPE_TAG_BOOLEAN: case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: case GI_TYPE_TAG_FLOAT: case GI_TYPE_TAG_DOUBLE: case GI_TYPE_TAG_GTYPE: case GI_TYPE_TAG_UNICHAR: break; case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_UTF8: /* With allow-none support the string could be NULL */ if ((arg->v_string != NULL && (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)) || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { g_free (arg->v_string); } break; case GI_TYPE_TAG_ARRAY: { GArray *array; gsize i; if (arg->v_pointer == NULL) { return; } array = arg->v_pointer; if ( (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { GITypeInfo *item_type_info; GITransfer item_transfer; item_type_info = g_type_info_get_param_type (type_info, 0); item_transfer = direction == GI_DIRECTION_IN ? GI_TRANSFER_NOTHING : GI_TRANSFER_EVERYTHING; /* Free the items */ for (i = 0; i < array->len; i++) { GIArgument *item; item = &_g_array_index (array, GIArgument, i); _pygi_argument_release (item, item_type_info, item_transfer, direction); } g_base_info_unref ( (GIBaseInfo *) item_type_info); } if ( (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { g_array_free (array, TRUE); } break; } case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *info; GIInfoType info_type; info = g_type_info_get_interface (type_info); info_type = g_base_info_get_type (info); switch (info_type) { case GI_INFO_TYPE_CALLBACK: /* TODO */ break; case GI_INFO_TYPE_BOXED: case GI_INFO_TYPE_STRUCT: case GI_INFO_TYPE_UNION: { GType type; if (arg->v_pointer == NULL) { return; } type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info); if (g_type_is_a (type, G_TYPE_VALUE)) { GValue *value; value = arg->v_pointer; if ( (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { g_value_unset (value); } if ( (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { g_slice_free (GValue, value); } } else if (g_type_is_a (type, G_TYPE_CLOSURE)) { if (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) { g_closure_unref (arg->v_pointer); } } else if (info_type == GI_INFO_TYPE_STRUCT && g_struct_info_is_foreign ((GIStructInfo*) info)) { if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING) { pygi_struct_foreign_release (info, arg->v_pointer); } } else if (g_type_is_a (type, G_TYPE_BOXED)) { } else if (g_type_is_a (type, G_TYPE_POINTER) || type == G_TYPE_NONE) { g_warn_if_fail (!g_type_info_is_pointer (type_info) || transfer == GI_TRANSFER_NOTHING); } break; } case GI_INFO_TYPE_ENUM: case GI_INFO_TYPE_FLAGS: break; case GI_INFO_TYPE_INTERFACE: case GI_INFO_TYPE_OBJECT: if (arg->v_pointer == NULL) { return; } if (is_out && transfer == GI_TRANSFER_EVERYTHING) { g_object_unref (arg->v_pointer); } break; default: g_assert_not_reached(); } g_base_info_unref (info); break; } case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: { GSList *list; if (arg->v_pointer == NULL) { return; } list = arg->v_pointer; if ( (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { GITypeInfo *item_type_info; GITransfer item_transfer; GSList *item; item_type_info = g_type_info_get_param_type (type_info, 0); g_assert (item_type_info != NULL); item_transfer = direction == GI_DIRECTION_IN ? GI_TRANSFER_NOTHING : GI_TRANSFER_EVERYTHING; /* Free the items */ for (item = list; item != NULL; item = g_slist_next (item)) { _pygi_argument_release ( (GIArgument *) &item->data, item_type_info, item_transfer, direction); } g_base_info_unref ( (GIBaseInfo *) item_type_info); } if ( (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { if (type_tag == GI_TYPE_TAG_GLIST) { g_list_free ( (GList *) list); } else { /* type_tag == GI_TYPE_TAG_GSLIST */ g_slist_free (list); } } break; } case GI_TYPE_TAG_GHASH: { GHashTable *hash_table; if (arg->v_pointer == NULL) { return; } hash_table = arg->v_pointer; if (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) { /* We created the table without a destroy function, so keys and * values need to be released. */ GITypeInfo *key_type_info; GITypeInfo *value_type_info; GITransfer item_transfer; GHashTableIter hash_table_iter; gpointer key; gpointer value; key_type_info = g_type_info_get_param_type (type_info, 0); g_assert (key_type_info != NULL); value_type_info = g_type_info_get_param_type (type_info, 1); g_assert (value_type_info != NULL); if (direction == GI_DIRECTION_IN) { item_transfer = GI_TRANSFER_NOTHING; } else { item_transfer = GI_TRANSFER_EVERYTHING; } g_hash_table_iter_init (&hash_table_iter, hash_table); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { _pygi_argument_release ( (GIArgument *) &key, key_type_info, item_transfer, direction); _pygi_argument_release ( (GIArgument *) &value, value_type_info, item_transfer, direction); } g_base_info_unref ( (GIBaseInfo *) key_type_info); g_base_info_unref ( (GIBaseInfo *) value_type_info); } else if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_CONTAINER) { /* Be careful to avoid keys and values being freed if the * callee gave a destroy function. */ g_hash_table_steal_all (hash_table); } if ( (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { g_hash_table_unref (hash_table); } break; } case GI_TYPE_TAG_ERROR: { GError *error; if (arg->v_pointer == NULL) { return; } error = * (GError **) arg->v_pointer; if (error != NULL) { g_error_free (error); } g_slice_free (GError *, arg->v_pointer); break; } } }
static PyObject * _wrap_g_field_info_set_value (PyGIBaseInfo *self, PyObject *args) { PyObject *instance; PyObject *py_value; GIBaseInfo *container_info; GIInfoType container_info_type; gpointer pointer; GITypeInfo *field_type_info; GIArgument value; PyObject *retval = NULL; if (!PyArg_ParseTuple (args, "OO:FieldInfo.set_value", &instance, &py_value)) { return NULL; } container_info = g_base_info_get_container (self->info); g_assert (container_info != NULL); /* Check the instance. */ if (!_pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) container_info, TRUE, instance)) { _PyGI_ERROR_PREFIX ("argument 1: "); return NULL; } /* Get the pointer to the container. */ container_info_type = g_base_info_get_type (container_info); switch (container_info_type) { case GI_INFO_TYPE_UNION: case GI_INFO_TYPE_STRUCT: pointer = pyg_boxed_get (instance, void); break; case GI_INFO_TYPE_OBJECT: pointer = pygobject_get (instance); break; default: /* Other types don't have fields. */ g_assert_not_reached(); } field_type_info = g_field_info_get_type ( (GIFieldInfo *) self->info); /* Check the value. */ { gboolean retval; retval = _pygi_g_type_info_check_object (field_type_info, py_value, TRUE); if (retval < 0) { goto out; } if (!retval) { _PyGI_ERROR_PREFIX ("argument 2: "); goto out; } } /* Set the field's value. */ /* A few types are not handled by g_field_info_set_field, so do it here. */ if (!g_type_info_is_pointer (field_type_info) && g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_INTERFACE) { GIBaseInfo *info; GIInfoType info_type; if (! (g_field_info_get_flags ( (GIFieldInfo *) self->info) & GI_FIELD_IS_WRITABLE)) { PyErr_SetString (PyExc_RuntimeError, "field is not writable"); goto out; } info = g_type_info_get_interface (field_type_info); info_type = g_base_info_get_type (info); switch (info_type) { case GI_INFO_TYPE_UNION: PyErr_SetString (PyExc_NotImplementedError, "setting an union is not supported yet"); goto out; case GI_INFO_TYPE_STRUCT: { gboolean is_simple; gsize offset; gssize size; is_simple = pygi_g_struct_info_is_simple ( (GIStructInfo *) info); if (!is_simple) { PyErr_SetString (PyExc_TypeError, "cannot set a structure which has no well-defined ownership transfer rules"); g_base_info_unref (info); goto out; } value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_NOTHING); if (PyErr_Occurred()) { g_base_info_unref (info); goto out; } offset = g_field_info_get_offset ( (GIFieldInfo *) self->info); size = g_struct_info_get_size ( (GIStructInfo *) info); g_assert (size > 0); g_memmove (pointer + offset, value.v_pointer, size); g_base_info_unref (info); retval = Py_None; goto out; } default: /* Fallback. */ break; } g_base_info_unref (info); } value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_EVERYTHING); if (PyErr_Occurred()) { goto out; } if (!g_field_info_set_field ( (GIFieldInfo *) self->info, pointer, &value)) { _pygi_argument_release (&value, field_type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); PyErr_SetString (PyExc_RuntimeError, "unable to set value for field"); goto out; } retval = Py_None; out: g_base_info_unref ( (GIBaseInfo *) field_type_info); Py_XINCREF (retval); return retval; }