Example #1
0
static PyObject *
_wrap_g_constant_info_get_value (PyGIBaseInfo *self)
{
    GITypeInfo *type_info;
    GIArgument value;
    PyObject *py_value;
    gboolean free_array = FALSE;

    if (g_constant_info_get_value ( (GIConstantInfo *) self->info, &value) < 0) {
        PyErr_SetString (PyExc_RuntimeError, "unable to get value");
        return NULL;
    }

    type_info = g_constant_info_get_type ( (GIConstantInfo *) self->info);

    if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY) {
        value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL,
                                                   type_info, &free_array);
    }

    py_value = _pygi_argument_to_object (&value, type_info, GI_TRANSFER_NOTHING);
    
    if (free_array) {
        g_array_free (value.v_pointer, FALSE);
    }

    g_constant_info_free_value (self->info, &value);
    g_base_info_unref ( (GIBaseInfo *) type_info);

    return py_value;
}
Example #2
0
static PyObject *
_wrap_g_constant_info_get_value (PyGIBaseInfo *self)
{
    GITypeInfo *type_info;
    GIArgument value;
    PyObject *py_value;

    if (g_constant_info_get_value ( (GIConstantInfo *) self->info, &value) < 0) {
        PyErr_SetString (PyExc_RuntimeError, "unable to get value");
        return NULL;
    }

    type_info = g_constant_info_get_type ( (GIConstantInfo *) self->info);

    py_value = _pygi_argument_to_object (&value, type_info, GI_TRANSFER_NOTHING);

    g_base_info_unref ( (GIBaseInfo *) type_info);

    return py_value;
}
Example #3
0
static PyObject *
_wrap_g_field_info_get_value (PyGIBaseInfo *self,
                              PyObject     *args)
{
    PyObject *instance;
    GIBaseInfo *container_info;
    GIInfoType container_info_type;
    gpointer pointer;
    GITypeInfo *field_type_info;
    GIArgument value;
    PyObject *py_value = NULL;
    gboolean free_array = FALSE;

    memset(&value, 0, sizeof(GIArgument));

    if (!PyArg_ParseTuple (args, "O:FieldInfo.get_value", &instance)) {
        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();
    }

    /* Get the field's value. */
    field_type_info = g_field_info_get_type ( (GIFieldInfo *) self->info);

    /* A few types are not handled by g_field_info_get_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_READABLE)) {
            PyErr_SetString (PyExc_RuntimeError, "field is not readable");
            goto out;
        }

        info = g_type_info_get_interface (field_type_info);

        info_type = g_base_info_get_type (info);

        g_base_info_unref (info);

        switch (info_type) {
            case GI_INFO_TYPE_UNION:
                PyErr_SetString (PyExc_NotImplementedError, "getting an union is not supported yet");
                goto out;
            case GI_INFO_TYPE_STRUCT:
            {
                gsize offset;

                offset = g_field_info_get_offset ( (GIFieldInfo *) self->info);

                value.v_pointer = (char*) pointer + offset;

                goto argument_to_object;
            }
            default:
                /* Fallback. */
                break;
        }
    }

    if (!g_field_info_get_field ( (GIFieldInfo *) self->info, pointer, &value)) {
        PyErr_SetString (PyExc_RuntimeError, "unable to get the value");
        goto out;
    }

    if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) {
        value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL,
                                                   field_type_info, &free_array);
    }

argument_to_object:
    py_value = _pygi_argument_to_object (&value, field_type_info, GI_TRANSFER_NOTHING);

    if (free_array) {
        g_array_free (value.v_pointer, FALSE);
    }

out:
    g_base_info_unref ( (GIBaseInfo *) field_type_info);

    return py_value;
}
Example #4
0
static void
pygi_signal_closure_marshal(GClosure *closure,
                            GValue *return_value,
                            guint n_param_values,
                            const GValue *param_values,
                            gpointer invocation_hint,
                            gpointer marshal_data)
{
    PyGILState_STATE state;
    PyGClosure *pc = (PyGClosure *)closure;
    PyObject *params, *ret = NULL;
    guint i;
    GISignalInfo *signal_info;
    gint n_sig_info_args;
    gint sig_info_highest_arg;
    GSList *list_item = NULL;
    GSList *pass_by_ref_structs = NULL;

    state = PyGILState_Ensure();

    signal_info = ((PyGISignalClosure *)closure)->signal_info;
    n_sig_info_args = g_callable_info_get_n_args(signal_info);
    /* the first argument to a signal callback is instance,
       but instance is not counted in the introspection data */
    sig_info_highest_arg = n_sig_info_args + 1;
    g_assert_cmpint(sig_info_highest_arg, ==, n_param_values);

    /* construct Python tuple for the parameter values */
    params = PyTuple_New(n_param_values);
    for (i = 0; i < n_param_values; i++) {
        /* swap in a different initial data for connect_object() */
        if (i == 0 && G_CCLOSURE_SWAP_DATA(closure)) {
            g_return_if_fail(pc->swap_data != NULL);
            Py_INCREF(pc->swap_data);
            PyTuple_SetItem(params, 0, pc->swap_data);

        } else if (i == 0) {
            PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);

            if (!item) {
                goto out;
            }
            PyTuple_SetItem(params, i, item);

        } else if (i < sig_info_highest_arg) {
            GIArgInfo arg_info;
            GITypeInfo type_info;
            GITypeTag type_tag;
            GIArgument arg = { 0, };
            PyObject *item = NULL;
            gboolean free_array = FALSE;
            gboolean pass_struct_by_ref = FALSE;

            g_callable_info_load_arg(signal_info, i - 1, &arg_info);
            g_arg_info_load_type(&arg_info, &type_info);

            arg = _pygi_argument_from_g_value(&param_values[i], &type_info);

            type_tag = g_type_info_get_tag (&type_info);
            if (type_tag == GI_TYPE_TAG_ARRAY) {
                /* Skip the self argument of param_values */
                arg.v_pointer = _pygi_argument_to_array (&arg,
                                                         _pygi_argument_array_length_marshal,
                                                         (void *)(param_values + 1),
                                                         signal_info,
                                                         &type_info,
                                                         &free_array);
            }

            /* Hack to ensure struct arguments are passed-by-reference allowing
             * callback implementors to modify the struct values. This is needed
             * for keeping backwards compatibility and should be removed in future
             * versions which support signal output arguments as return values.
             * See: https://bugzilla.gnome.org/show_bug.cgi?id=735486
             *
             * Note the logic here must match the logic path taken in _pygi_argument_to_object.
             */
            if (type_tag == GI_TYPE_TAG_INTERFACE) {
                GIBaseInfo *info = g_type_info_get_interface (&type_info);
                GIInfoType info_type = g_base_info_get_type (info);

                if (info_type == GI_INFO_TYPE_STRUCT ||
                        info_type == GI_INFO_TYPE_BOXED ||
                        info_type == GI_INFO_TYPE_UNION) {

                    GType gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *) info);
                    gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) &&
                                          (g_struct_info_is_foreign ((GIStructInfo *) info));

                    if (!is_foreign && !g_type_is_a (gtype, G_TYPE_VALUE) &&
                            g_type_is_a (gtype, G_TYPE_BOXED)) {
                        pass_struct_by_ref = TRUE;
                    }
                }

                g_base_info_unref (info);
            }

            if (pass_struct_by_ref) {
                /* transfer everything will ensure the struct is not copied when wrapped. */
                item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_EVERYTHING);
                if (item && PyObject_IsInstance (item, (PyObject *) &PyGIBoxed_Type)) {
                    ((PyGBoxed *)item)->free_on_dealloc = FALSE;
                    pass_by_ref_structs = g_slist_prepend (pass_by_ref_structs, item);
                }

            } else {
                item = _pygi_argument_to_object (&arg, &type_info, GI_TRANSFER_NOTHING);
            }

            if (free_array) {
                g_array_free (arg.v_pointer, FALSE);
            }

            if (item == NULL) {
                PyErr_Print ();
                goto out;
            }
            PyTuple_SetItem(params, i, item);
        }
    }
    /* params passed to function may have extra arguments */
    if (pc->extra_args) {
        PyObject *tuple = params;
        params = PySequence_Concat(tuple, pc->extra_args);
        Py_DECREF(tuple);
    }
    ret = PyObject_CallObject(pc->callback, params);
    if (ret == NULL) {
        if (pc->exception_handler)
            pc->exception_handler(return_value, n_param_values, param_values);
        else
            PyErr_Print();
        goto out;
    }

    if (G_IS_VALUE(return_value) && pyg_value_from_pyobject(return_value, ret) != 0) {
        PyErr_SetString(PyExc_TypeError,
                        "can't convert return value to desired type");

        if (pc->exception_handler)
            pc->exception_handler(return_value, n_param_values, param_values);
        else
            PyErr_Print();
    }
    Py_DECREF(ret);

    /* Run through the list of structs which have been passed by reference and
     * check if they are being held longer than the duration of the callback
     * execution. This is determined if the ref count is greater than 1.
     * A single ref is held by the argument list and any more would mean the callback
     * stored a ref somewhere else. In this case we make an internal copy of
     * the boxed struct so Python can own the memory to it.
     */
    list_item = pass_by_ref_structs;
    while (list_item) {
        PyObject *item = list_item->data;
        if (item->ob_refcnt > 1) {
            _pygi_boxed_copy_in_place ((PyGIBoxed *)item);
        }
        list_item = g_slist_next (list_item);
    }

 out:
    g_slist_free (pass_by_ref_structs);
    Py_DECREF(params);
    PyGILState_Release(state);
}
Example #5
0
void
_pygi_closure_handle (ffi_cif *cif,
                      void    *result,
                      void   **args,
                      void    *data)
{
    PyGILState_STATE state;
    PyGICClosure *closure = data;
    gint n_args, i;
    GIArgInfo  *arg_info;
    GIDirection arg_direction;
    GITypeInfo *arg_type;
    GITransfer arg_transfer;
    GITypeTag  arg_tag;
    GITypeTag  return_tag;
    GITransfer return_transfer;
    GITypeInfo *return_type;
    PyObject *retval;
    PyObject *py_args;
    PyObject *pyarg;
    gint n_in_args, n_out_args;


    /* Lock the GIL as we are coming into this code without the lock and we
      may be executing python code */
    state = PyGILState_Ensure();

    return_type = g_callable_info_get_return_type(closure->info);
    return_tag = g_type_info_get_tag(return_type);
    return_transfer = g_callable_info_get_caller_owns(closure->info);

    n_args = g_callable_info_get_n_args (closure->info);

    py_args = PyTuple_New(n_args);
    if (py_args == NULL) {
        PyErr_Clear();
        goto end;
    }

    n_in_args = 0;

    for (i = 0; i < n_args; i++) {
        arg_info = g_callable_info_get_arg (closure->info, i);
        arg_type = g_arg_info_get_type (arg_info);
        arg_transfer = g_arg_info_get_ownership_transfer(arg_info);
        arg_tag = g_type_info_get_tag(arg_type);
        arg_direction = g_arg_info_get_direction(arg_info);
        switch (arg_tag) {
        case GI_TYPE_TAG_VOID:
        {
            if (g_type_info_is_pointer(arg_type)) {
                if (PyTuple_SetItem(py_args, n_in_args, closure->user_data) != 0) {
                    PyErr_Clear();
                    goto end;
                }
                n_in_args++;
                continue;
            }
        }
        case GI_TYPE_TAG_ERROR:
        {
            continue;
        }
        default:
        {
            pyarg = _pygi_argument_to_object (args[i],
                                              arg_type,
                                              arg_transfer);

            if(PyTuple_SetItem(py_args, n_in_args, pyarg) != 0) {
                PyErr_Clear();
                goto end;
            }
            n_in_args++;
            g_base_info_unref((GIBaseInfo*)arg_info);
            g_base_info_unref((GIBaseInfo*)arg_type);
        }
        }

    }

    if(_PyTuple_Resize (&py_args, n_in_args) != 0) {
        PyErr_Clear();
        goto end;
    }

    retval = PyObject_CallObject((PyObject *)closure->function, py_args);

    Py_DECREF(py_args);

    if (retval == NULL) {
        goto end;
    }

    *(GArgument*)result = _pygi_argument_from_object(retval, return_type, return_transfer);

end:
    g_base_info_unref((GIBaseInfo*)return_type);

    PyGILState_Release(state);

    if (closure->user_data)
        Py_XDECREF(closure->user_data);

    /* Now that the closure has finished we can make a decision about how
       to free it.  Scope call gets free'd now, scope notified will be freed
       when the notify is called and we can free async anytime we want
       once we return from this function */
    switch (closure->scope) {
    case GI_SCOPE_TYPE_CALL:
        _pygi_invoke_closure_free(closure);
        break;
    case GI_SCOPE_TYPE_NOTIFIED:
        break;
    case GI_SCOPE_TYPE_ASYNC:
        /* Append this PyGICClosure to a list of closure that we will free
           after we're done with this function invokation */
        async_free_list = g_slist_prepend(async_free_list, closure);
        break;
    default:
        g_assert_not_reached();
    }
}
Example #6
0
PyObject *
pygi_get_property_value_real (PyGObject *instance,
                              const gchar *attr_name)
{
    GType g_type;
    GIPropertyInfo *property_info = NULL;
    char *property_name = g_strdup (attr_name);
    GParamSpec *pspec = NULL;
    GValue value = { 0, };
    GIArgument arg = { 0, };
    PyObject *py_value = NULL;
    GITypeInfo *type_info = NULL;
    GITransfer transfer;

    canonicalize_key (property_name);

    g_type = pyg_type_from_object ((PyObject *)instance);
    property_info = _pygi_lookup_property_from_g_type (g_type, property_name);

    if (property_info == NULL)
        goto out;

    pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (instance->obj),
                                          attr_name);
    if (pspec == NULL)
        goto out;

    g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
    g_object_get_property (instance->obj, attr_name, &value);

    type_info = g_property_info_get_type (property_info);
    transfer = g_property_info_get_ownership_transfer (property_info);

    GITypeTag type_tag = g_type_info_get_tag (type_info);
    switch (type_tag) {
        case GI_TYPE_TAG_BOOLEAN:
            arg.v_boolean = g_value_get_boolean (&value);
            break;
        case GI_TYPE_TAG_INT8:
            arg.v_int8 = g_value_get_schar (&value);
            break;
        case GI_TYPE_TAG_INT16:
        case GI_TYPE_TAG_INT32:
            if (G_VALUE_HOLDS_LONG (&value))
                arg.v_long = g_value_get_long (&value);
            else
                arg.v_int = g_value_get_int (&value);
            break;
        case GI_TYPE_TAG_INT64:
            if (G_VALUE_HOLDS_LONG (&value))
                arg.v_long = g_value_get_long (&value);
            else
                arg.v_int64 = g_value_get_int64 (&value);
            break;
        case GI_TYPE_TAG_UINT8:
            arg.v_uint8 = g_value_get_uchar (&value);
            break;
        case GI_TYPE_TAG_UINT16:
        case GI_TYPE_TAG_UINT32:
            if (G_VALUE_HOLDS_ULONG (&value))
                arg.v_ulong = g_value_get_ulong (&value);
            else
                arg.v_uint = g_value_get_uint (&value);
            break;
        case GI_TYPE_TAG_UINT64:
            if (G_VALUE_HOLDS_ULONG (&value))
                arg.v_ulong = g_value_get_ulong (&value);
            else
                arg.v_uint64 = g_value_get_uint64 (&value);
            break;
        case GI_TYPE_TAG_FLOAT:
            arg.v_float = g_value_get_float (&value);
            break;
        case GI_TYPE_TAG_DOUBLE:
            arg.v_double = g_value_get_double (&value);
            break;
        case GI_TYPE_TAG_GTYPE:
            arg.v_size = g_value_get_gtype (&value);
            break;
        case GI_TYPE_TAG_UTF8:
        case GI_TYPE_TAG_FILENAME:
            arg.v_string = g_value_dup_string (&value);
            break;
        case GI_TYPE_TAG_INTERFACE:
        {
            GIBaseInfo *info;
            GIInfoType info_type;
            GType type;

            info = g_type_info_get_interface (type_info);
            type = g_registered_type_info_get_g_type (info);
            info_type = g_base_info_get_type (info);

            g_base_info_unref (info);

            switch (info_type) {
                case GI_INFO_TYPE_ENUM:
                    arg.v_int32 = g_value_get_enum (&value);
                    break;
                case GI_INFO_TYPE_INTERFACE:
                case GI_INFO_TYPE_OBJECT:
                    arg.v_pointer = g_value_get_object (&value);
                    break;
                case GI_INFO_TYPE_BOXED:
                case GI_INFO_TYPE_STRUCT:
                case GI_INFO_TYPE_UNION:

                    if (g_type_is_a (type, G_TYPE_BOXED)) {
                        arg.v_pointer = g_value_get_boxed (&value);
                    } else if (g_type_is_a (type, G_TYPE_POINTER)) {
                        arg.v_pointer = g_value_get_pointer (&value);
                    } else {
                        PyErr_Format (PyExc_NotImplementedError,
                                      "Retrieving properties of type '%s' is not implemented",
                                      g_type_name (type));
                    }
                    break;
                default:
                    PyErr_Format (PyExc_NotImplementedError,
                                  "Retrieving properties of type '%s' is not implemented",
                                  g_type_name (type));
                    goto out;
            }
            break;
        }
        case GI_TYPE_TAG_GHASH:
            arg.v_pointer = g_value_get_boxed (&value);
            break;
        case GI_TYPE_TAG_GLIST:
            arg.v_pointer = g_value_get_pointer (&value);
            break;
        case GI_TYPE_TAG_ARRAY:
        {
            gchar** strings;
            GArray *arg_items;
            int i;

            strings = g_value_get_boxed (&value);
            if (strings == NULL)
                arg.v_pointer = NULL;
            else {
                arg_items = g_array_sized_new (TRUE, TRUE, sizeof (GIArgument), g_strv_length (strings));
                g_array_set_size (arg_items, g_strv_length (strings));
                for (i = 0; strings[i] != NULL; ++i) {
                    g_array_index (arg_items, GIArgument, i).v_string = strings[i];
                }
                arg.v_pointer = arg_items;
            }
            break;
        }
        default:
            PyErr_Format (PyExc_NotImplementedError,
                          "Retrieving properties of type %s is not implemented",
                          g_type_tag_to_string (g_type_info_get_tag (type_info)));
            goto out;
    }

    py_value = _pygi_argument_to_object (&arg, type_info, transfer);

out:
    g_free (property_name);
    if (property_info != NULL)
        g_base_info_unref (property_info);
    if (type_info != NULL)
        g_base_info_unref (type_info);

    return py_value;
}
Example #7
0
/**
 * _pygi_argument_to_object:
 * @arg: The argument to convert to an object.
 * @type_info: Type info for @arg
 * @transfer:
 *
 * If the argument is of type array, it must be encoded in a GArray, by calling
 * _pygi_argument_to_array(). This logic can not be folded into this method
 * as determining array lengths may require access to method call arguments.
 *
 * Returns: A PyObject representing @arg
 */
PyObject *
_pygi_argument_to_object (GIArgument  *arg,
                          GITypeInfo *type_info,
                          GITransfer transfer)
{
    GITypeTag type_tag;
    PyObject *object = NULL;

    type_tag = g_type_info_get_tag (type_info);
    object = _pygi_marshal_to_py_basic_type (arg, type_tag, transfer);
    if (object)
        return object;

    switch (type_tag) {
        case GI_TYPE_TAG_VOID:
        {
            if (g_type_info_is_pointer (type_info)) {
                g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
                object = PyLong_FromVoidPtr (arg->v_pointer);
            }
            break;
        }
        case GI_TYPE_TAG_ARRAY:
        {
            /* Arrays are assumed to be packed in a GArray */
            GArray *array;
            GITypeInfo *item_type_info;
            GITypeTag item_type_tag;
            GITransfer item_transfer;
            gsize i, item_size;

            if (arg->v_pointer == NULL)
                return PyList_New (0);
            
            item_type_info = g_type_info_get_param_type (type_info, 0);
            g_assert (item_type_info != NULL);

            item_type_tag = g_type_info_get_tag (item_type_info);
            item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
            
            array = arg->v_pointer;
            item_size = g_array_get_element_size (array);
            
            if (G_UNLIKELY (item_size > sizeof(GIArgument))) {
                g_critical ("Stack overflow protection. "
                            "Can't copy array element into GIArgument.");
                return PyList_New (0);
            }

            if (item_type_tag == GI_TYPE_TAG_UINT8) {
                /* Return as a byte array */
                object = PYGLIB_PyBytes_FromStringAndSize (array->data, array->len);
            } else {
                object = PyList_New (array->len);
                if (object == NULL) {
                    g_critical ("Failure to allocate array for %u items", array->len);
                    g_base_info_unref ( (GIBaseInfo *) item_type_info);
                    break;
                }

                for (i = 0; i < array->len; i++) {
                    GIArgument item = { 0 };
                    PyObject *py_item;
                    
                    memcpy (&item, array->data + i * item_size, item_size);

                    py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer);
                    if (py_item == NULL) {
                        Py_CLEAR (object);
                        _PyGI_ERROR_PREFIX ("Item %zu: ", i);
                        break;
                    }

                    PyList_SET_ITEM (object, i, py_item);
                }
            }

            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:
                {
                    g_assert_not_reached();
                }
                case GI_INFO_TYPE_BOXED:
                case GI_INFO_TYPE_STRUCT:
                case GI_INFO_TYPE_UNION:
                {
                    PyObject *py_type;
                    GType g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
                    gboolean is_foreign = (info_type == GI_INFO_TYPE_STRUCT) &&
                                          (g_struct_info_is_foreign ((GIStructInfo *) info));

                    /* Special case variant and none to force loading from py module. */
                    if (g_type == G_TYPE_VARIANT || g_type == G_TYPE_NONE) {
                        py_type = _pygi_type_import_by_gi_info (info);
                    } else {
                        py_type = _pygi_type_get_from_g_type (g_type);
                    }

                    object = pygi_arg_struct_to_py_marshal (arg,
                                                            info, /*interface_info*/
                                                            g_type,
                                                            py_type,
                                                            transfer,
                                                            FALSE, /*is_allocated*/
                                                            is_foreign);

                    Py_XDECREF (py_type);
                    break;
                }
                case GI_INFO_TYPE_ENUM:
                case GI_INFO_TYPE_FLAGS:
                {
                    GType type;

                    type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);

                    if (type == G_TYPE_NONE) {
                        /* An enum with a GType of None is an enum without GType */
                        PyObject *py_type = _pygi_type_import_by_gi_info (info);
                        PyObject *py_args = NULL;

                        if (!py_type)
                            return NULL;

                        py_args = PyTuple_New (1);
                        if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (arg->v_int)) != 0) {
                            Py_DECREF (py_args);
                            Py_DECREF (py_type);
                            return NULL;
                        }

                        object = PyObject_CallFunction (py_type, "i", arg->v_int);

                        Py_DECREF (py_args);
                        Py_DECREF (py_type);

                    } else if (info_type == GI_INFO_TYPE_ENUM) {
                        object = pyg_enum_from_gtype (type, arg->v_int);
                    } else {
                        object = pyg_flags_from_gtype (type, arg->v_uint);
                    }

                    break;
                }
                case GI_INFO_TYPE_INTERFACE:
                case GI_INFO_TYPE_OBJECT:
                    object = pygi_arg_gobject_to_py_called_from_c (arg, transfer);

                    break;
                default:
                    g_assert_not_reached();
            }

            g_base_info_unref (info);
            break;
        }
        case GI_TYPE_TAG_GLIST:
        case GI_TYPE_TAG_GSLIST:
        {
            GSList *list;
            gsize length;
            GITypeInfo *item_type_info;
            GITransfer item_transfer;
            gsize i;

            list = arg->v_pointer;
            length = g_slist_length (list);

            object = PyList_New (length);
            if (object == NULL) {
                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 = 0; list != NULL; list = g_slist_next (list), i++) {
                GIArgument item;
                PyObject *py_item;

                item.v_pointer = list->data;

                py_item = _pygi_argument_to_object (&item, item_type_info, item_transfer);
                if (py_item == NULL) {
                    Py_CLEAR (object);
                    _PyGI_ERROR_PREFIX ("Item %zu: ", i);
                    break;
                }

                PyList_SET_ITEM (object, i, py_item);
            }

            g_base_info_unref ( (GIBaseInfo *) item_type_info);
            break;
        }
        case GI_TYPE_TAG_GHASH:
        {
            GITypeInfo *key_type_info;
            GITypeInfo *value_type_info;
            GITransfer item_transfer;
            GHashTableIter hash_table_iter;
            GIArgument key;
            GIArgument value;

            if (arg->v_pointer == NULL) {
                object = Py_None;
                Py_INCREF (object);
                break;
            }

            object = PyDict_New();
            if (object == NULL) {
                break;
            }

            key_type_info = g_type_info_get_param_type (type_info, 0);
            g_assert (key_type_info != NULL);
            g_assert (g_type_info_get_tag (key_type_info) != GI_TYPE_TAG_VOID);

            value_type_info = g_type_info_get_param_type (type_info, 1);
            g_assert (value_type_info != NULL);
            g_assert (g_type_info_get_tag (value_type_info) != GI_TYPE_TAG_VOID);

            item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;

            g_hash_table_iter_init (&hash_table_iter, (GHashTable *) arg->v_pointer);
            while (g_hash_table_iter_next (&hash_table_iter, &key.v_pointer, &value.v_pointer)) {
                PyObject *py_key;
                PyObject *py_value;
                int retval;

                py_key = _pygi_argument_to_object (&key, key_type_info, item_transfer);
                if (py_key == NULL) {
                    break;
                }

                _pygi_hash_pointer_to_arg (&value, g_type_info_get_tag (value_type_info));
                py_value = _pygi_argument_to_object (&value, value_type_info, item_transfer);
                if (py_value == NULL) {
                    Py_DECREF (py_key);
                    break;
                }

                retval = PyDict_SetItem (object, py_key, py_value);

                Py_DECREF (py_key);
                Py_DECREF (py_value);

                if (retval < 0) {
                    Py_CLEAR (object);
                    break;
                }
            }

            g_base_info_unref ( (GIBaseInfo *) key_type_info);
            g_base_info_unref ( (GIBaseInfo *) value_type_info);
            break;
        }
        case GI_TYPE_TAG_ERROR:
        {
            GError *error = (GError *) arg->v_pointer;
            if (error != NULL && transfer == GI_TRANSFER_NOTHING) {
                /* If we have not been transferred the ownership we must copy
                 * the error, because pygi_error_check() is going to free it.
                 */
                error = g_error_copy (error);
            }

            if (pygi_error_check (&error)) {
                PyObject *err_type;
                PyObject *err_value;
                PyObject *err_trace;
                PyErr_Fetch (&err_type, &err_value, &err_trace);
                Py_XDECREF (err_type);
                Py_XDECREF (err_trace);
                object = err_value;
            } else {
                object = Py_None;
                Py_INCREF (object);
                break;
            }
            break;
        }
        default:
        {
            g_assert_not_reached();
        }
    }

    return object;
}