static gboolean
_pygi_marshal_from_py_utf8 (PyObject          *py_arg,
                            GIArgument        *arg,
                            gpointer          *cleanup_data)
{
    gchar *string_;

    if (py_arg == Py_None) {
        arg->v_pointer = NULL;
        return TRUE;
    }

    if (PyUnicode_Check (py_arg)) {
        PyObject *pystr_obj = PyUnicode_AsUTF8String (py_arg);
        if (!pystr_obj)
            return FALSE;

        string_ = g_strdup (PYGLIB_PyBytes_AsString (pystr_obj));
        Py_DECREF (pystr_obj);
    }
#if PY_VERSION_HEX < 0x03000000
    else if (PyString_Check (py_arg)) {
        string_ = g_strdup (PyString_AsString (py_arg));
    }
#endif
    else {
        PyErr_Format (PyExc_TypeError, "Must be string, not %s",
                      py_arg->ob_type->tp_name);
        return FALSE;
    }

    arg->v_string = string_;
    *cleanup_data = arg->v_string;
    return TRUE;
}
static gboolean
_pygi_marshal_from_py_unichar (PyObject          *py_arg,
                               GIArgument        *arg)
{
    Py_ssize_t size;
    gchar *string_;

    if (py_arg == Py_None) {
        arg->v_uint32 = 0;
        return FALSE;
    }

    if (PyUnicode_Check (py_arg)) {
       PyObject *py_bytes;

       size = PyUnicode_GET_SIZE (py_arg);
       py_bytes = PyUnicode_AsUTF8String (py_arg);
       if (!py_bytes)
           return FALSE;

       string_ = g_strdup(PYGLIB_PyBytes_AsString (py_bytes));
       Py_DECREF (py_bytes);

#if PY_VERSION_HEX < 0x03000000
    } else if (PyString_Check (py_arg)) {
       PyObject *pyuni = PyUnicode_FromEncodedObject (py_arg, "UTF-8", "strict");
       if (!pyuni)
           return FALSE;

       size = PyUnicode_GET_SIZE (pyuni);
       string_ = g_strdup (PyString_AsString(py_arg));
       Py_DECREF (pyuni);
#endif
    } else {
       PyErr_Format (PyExc_TypeError, "Must be string, not %s",
                     py_arg->ob_type->tp_name);
       return FALSE;
    }

    if (size != 1) {
       PyErr_Format (PyExc_TypeError, "Must be a one character string, not %lld characters",
                     (long long) size);
       g_free (string_);
       return FALSE;
    }

    arg->v_uint32 = g_utf8_get_char (string_);
    g_free (string_);

    return TRUE;
}
static gboolean
_pygi_marshal_from_py_filename (PyObject          *py_arg,
                                GIArgument        *arg,
                                gpointer          *cleanup_data)
{
    gchar *string_;
    GError *error = NULL;
    PyObject *tmp = NULL;

    if (PyUnicode_Check (py_arg)) {
        tmp = PyUnicode_AsUTF8String (py_arg);
        if (!tmp)
            return FALSE;

        string_ = PYGLIB_PyBytes_AsString (tmp);
    }
#if PY_VERSION_HEX < 0x03000000
    else if (PyString_Check (py_arg)) {
        string_ = PyString_AsString (py_arg);
    }
#endif
    else {
        PyErr_Format (PyExc_TypeError, "Must be string, not %s",
                      py_arg->ob_type->tp_name);
        return FALSE;
    }

    arg->v_string = g_filename_from_utf8 (string_, -1, NULL, NULL, &error);
    Py_XDECREF (tmp);

    if (arg->v_string == NULL) {
        PyErr_SetString (PyExc_Exception, error->message);
        g_error_free (error);
        /* TODO: Convert the error to an exception. */
        return FALSE;
    }

    *cleanup_data = arg->v_string;
    return TRUE;
}
gboolean
_pygi_marshal_from_py_basic_type (PyObject   *object,   /* in */
                                  GIArgument *arg,      /* out */
                                  GITypeTag   type_tag,
                                  GITransfer  transfer,
                                  gpointer   *cleanup_data /* out */)
{
    switch (type_tag) {
        case GI_TYPE_TAG_VOID:
            g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
            if (object == Py_None) {
                arg->v_pointer = NULL;
            } else if (!PYGLIB_PyLong_Check(object)  && !PyLong_Check(object)) {
                PyErr_SetString(PyExc_TypeError,
                    "Pointer assignment is restricted to integer values. "
                    "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599");
            } else {
                arg->v_pointer = PyLong_AsVoidPtr (object);
                *cleanup_data = arg->v_pointer;
            }
            break;
        case GI_TYPE_TAG_INT8:
        case GI_TYPE_TAG_UINT8:
            if (PYGLIB_PyBytes_Check (object)) {
                if (PYGLIB_PyBytes_Size (object) != 1) {
                    PyErr_Format (PyExc_TypeError, "Must be a single character");
                    return FALSE;
                }
                if (type_tag == GI_TYPE_TAG_INT8) {
                    arg->v_int8 = (gint8)(PYGLIB_PyBytes_AsString (object)[0]);
                } else {
                    arg->v_uint8 = (guint8)(PYGLIB_PyBytes_AsString (object)[0]);
                }
            } else {
                return _pygi_marshal_from_py_long (object, arg, type_tag, transfer);
            }
            break;
        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:
            return _pygi_marshal_from_py_long (object, arg, type_tag, transfer);

        case GI_TYPE_TAG_BOOLEAN:
            arg->v_boolean = PyObject_IsTrue (object);
            break;

        case GI_TYPE_TAG_FLOAT:
            return _pygi_marshal_from_py_float (object, arg);

        case GI_TYPE_TAG_DOUBLE:
            return _pygi_marshal_from_py_double (object, arg);

        case GI_TYPE_TAG_GTYPE:
            return _pygi_marshal_from_py_gtype (object, arg);

        case GI_TYPE_TAG_UNICHAR:
            return _pygi_marshal_from_py_unichar (object, arg);

        case GI_TYPE_TAG_UTF8:
            return _pygi_marshal_from_py_utf8 (object, arg, cleanup_data);

        case GI_TYPE_TAG_FILENAME:
            return _pygi_marshal_from_py_filename (object, arg, cleanup_data);

        default:
            return FALSE;
    }

    if (PyErr_Occurred())
        return FALSE;

    return TRUE;
}
Exemple #5
0
/**
 * pyg_value_from_pyobject:
 * @value: the GValue object to store the converted value in.
 * @obj: the Python object to convert.
 *
 * This function converts a Python object and stores the result in a
 * GValue.  The GValue must be initialised in advance with
 * g_value_init().  If the Python object can't be converted to the
 * type of the GValue, then an error is returned.
 *
 * Returns: 0 on success, -1 on error.
 */
int
pyg_value_from_pyobject(GValue *value, PyObject *obj)
{
    PyObject *tmp;

    switch (G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value))) {
    case G_TYPE_INTERFACE:
	/* we only handle interface types that have a GObject prereq */
	if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_OBJECT)) {
	    if (obj == Py_None)
		g_value_set_object(value, NULL);
	    else {
		if (!PyObject_TypeCheck(obj, &PyGObject_Type)) {
		    return -1;
		}
		if (!G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
						G_VALUE_TYPE(value))) {
		    return -1;
		}
		g_value_set_object(value, pygobject_get(obj));
	    }
	} else {
	    return -1;
	}
	break;
    case G_TYPE_CHAR:
#if PY_VERSION_HEX < 0x03000000
	if (PyString_Check(obj)) {
	    g_value_set_char(value, PyString_AsString(obj)[0]);
	} else
#endif
	if (PyUnicode_Check(obj)) {
	    tmp = PyUnicode_AsUTF8String(obj);
	    g_value_set_char(value, PYGLIB_PyBytes_AsString(tmp)[0]);
	    Py_DECREF(tmp);
	} else {
	    PyErr_Clear();
	    return -1;
	}

	break;
    case G_TYPE_UCHAR:
	if (PYGLIB_PyLong_Check(obj)) {
	    glong val;
	    val = PYGLIB_PyLong_AsLong(obj);
	    if (val >= 0 && val <= 255)
	      g_value_set_uchar(value, (guchar)PYGLIB_PyLong_AsLong (obj));
	    else
	      return -1;
#if PY_VERSION_HEX < 0x03000000
	} else if (PyString_Check(obj)) {
	    g_value_set_uchar(value, PyString_AsString(obj)[0]);
#endif
	} else if (PyUnicode_Check(obj)) {
	    tmp = PyUnicode_AsUTF8String(obj);
	    g_value_set_uchar(value, PYGLIB_PyBytes_AsString(tmp)[0]);
	    Py_DECREF(tmp);
	} else {
	    PyErr_Clear();
	    return -1;
	}
	break;
    case G_TYPE_BOOLEAN:
	g_value_set_boolean(value, PyObject_IsTrue(obj));
	break;
    case G_TYPE_INT:
	g_value_set_int(value, PYGLIB_PyLong_AsLong(obj));
	break;
    case G_TYPE_UINT:
	{
	    if (PYGLIB_PyLong_Check(obj)) {
		glong val;

		val = PYGLIB_PyLong_AsLong(obj);
		if (val >= 0 && val <= G_MAXUINT)
		    g_value_set_uint(value, (guint)val);
		else
		    return -1;
	    } else {
		g_value_set_uint(value, PyLong_AsUnsignedLong(obj));
	    }
	}
	break;
    case G_TYPE_LONG:
	g_value_set_long(value, PYGLIB_PyLong_AsLong(obj));
	break;
    case G_TYPE_ULONG:
#if PY_VERSION_HEX < 0x03000000
	if (PyInt_Check(obj)) {
            long val;

            val = PYGLIB_PyLong_AsLong(obj);
            if (val < 0) {
                PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property");
                return -1;
            }
            g_value_set_ulong(value, (gulong)val);
        } else
#endif
        if (PyLong_Check(obj))
	    g_value_set_ulong(value, PyLong_AsUnsignedLong(obj));
        else
            return -1;
        break;
    case G_TYPE_INT64:
	g_value_set_int64(value, PyLong_AsLongLong(obj));
	break;
    case G_TYPE_UINT64:
#if PY_VERSION_HEX < 0x03000000
        if (PyInt_Check(obj)) {
            long v = PyInt_AsLong(obj);
            if (v < 0) {
                PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property");
                return -1;
            }
            g_value_set_uint64(value, v);
        } else
#endif
        if (PyLong_Check(obj))
            g_value_set_uint64(value, PyLong_AsUnsignedLongLong(obj));
        else
            return -1;
	break;
    case G_TYPE_ENUM:
	{
	    gint val = 0;
	    if (pyg_enum_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
		PyErr_Clear();
		return -1;
	    }
	    g_value_set_enum(value, val);
	}
	break;
    case G_TYPE_FLAGS:
	{
	    gint val = 0;
	    if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
		PyErr_Clear();
		return -1;
	    }
	    g_value_set_flags(value, val);
	}
	break;
    case G_TYPE_FLOAT:
	g_value_set_float(value, PyFloat_AsDouble(obj));
	break;
    case G_TYPE_DOUBLE:
	g_value_set_double(value, PyFloat_AsDouble(obj));
	break;
    case G_TYPE_STRING:
	if (obj == Py_None) {
	    g_value_set_string(value, NULL);
#if PY_VERSION_HEX < 0x03000000
	} else if (PyString_Check(obj)) {
	    g_value_set_string(value, PyString_AsString(obj));
#endif
	} else if (PyUnicode_Check(obj)) {
	    tmp = PyUnicode_AsUTF8String(obj);
	    g_value_set_string(value, PYGLIB_PyBytes_AsString(tmp));
	    Py_DECREF(tmp);
	} else {
	    PyErr_Clear();
	    return -1;
	}
	break;
    case G_TYPE_POINTER:
	if (obj == Py_None)
	    g_value_set_pointer(value, NULL);
	else if (PyObject_TypeCheck(obj, &PyGPointer_Type) &&
		   G_VALUE_HOLDS(value, ((PyGPointer *)obj)->gtype))
	    g_value_set_pointer(value, pyg_pointer_get(obj, gpointer));
	else if (PYGLIB_CPointer_Check(obj))
	    g_value_set_pointer(value, PYGLIB_CPointer_GetPointer(obj, NULL));
	else
	    return -1;
	break;
    case G_TYPE_BOXED: {
	PyGTypeMarshal *bm;

	if (obj == Py_None)
	    g_value_set_boxed(value, NULL);
	else if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT))
	    g_value_set_boxed(value, obj);
	else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) &&
		   G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype))
	    g_value_set_boxed(value, pyg_boxed_get(obj, gpointer));
        else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
            GType type;
            GValue *n_value;

            type = pyg_type_from_object((PyObject*)Py_TYPE(obj));
            if (G_UNLIKELY (! type)) {
                PyErr_Clear();
                return -1;
            }
            n_value = g_new0 (GValue, 1);
            g_value_init (n_value, type);
            g_value_take_boxed (value, n_value);
            return pyg_value_from_pyobject (n_value, obj);
        }
        else if (PySequence_Check(obj) &&
		   G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY))
	    return pyg_value_array_from_pyobject(value, obj, NULL);
	else if (PYGLIB_PyUnicode_Check(obj) &&
                 G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
            GString *string;
            char *buffer;
            Py_ssize_t len;
            if (PYGLIB_PyUnicode_AsStringAndSize(obj, &buffer, &len))
                return -1;
            string = g_string_new_len(buffer, len);
	    g_value_set_boxed(value, string);
	    g_string_free (string, TRUE);
            break;
        }
	else if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL)
	    return bm->tovalue(value, obj);
	else if (PYGLIB_CPointer_Check(obj))
	    g_value_set_boxed(value, PYGLIB_CPointer_GetPointer(obj, NULL));
	else
	    return -1;
	break;
    }
    case G_TYPE_PARAM:
	if (PyGParamSpec_Check(obj))
	    g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL));
	else
	    return -1;
	break;
    case G_TYPE_OBJECT:
	if (obj == Py_None) {
	    g_value_set_object(value, NULL);
	} else if (PyObject_TypeCheck(obj, &PyGObject_Type) &&
		   G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
					      G_VALUE_TYPE(value))) {
	    g_value_set_object(value, pygobject_get(obj));
	} else
	    return -1;
	break;
    default:
	{
	    PyGTypeMarshal *bm;
	    if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL)
		return bm->tovalue(value, obj);
	    break;
	}
    }
    if (PyErr_Occurred()) {
        g_value_unset(value);
        PyErr_Clear();
        return -1;
    }
    return 0;
}
Exemple #6
0
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;
}