예제 #1
0
static VALUE
rg_type(VALUE self)
{
    GIFieldInfo *info;

    info = SELF(self);
    return GI_BASE_INFO2RVAL_WITH_UNREF(g_field_info_get_type(info));
}
static void
generic_interface_init (gpointer iface, gpointer data)
{
	GIInterfaceInfo *info = data;
	GIStructInfo *struct_info;
	gint n, i;
	struct_info = g_interface_info_get_iface_struct (info);
	n = g_interface_info_get_n_vfuncs (info);
	for (i = 0; i < n; i++) {
		GIVFuncInfo *vfunc_info;
		const gchar *vfunc_name;
		GIFieldInfo *field_info;
		gint field_offset;
		GITypeInfo *field_type_info;
		gchar *perl_method_name;
		GPerlI11nPerlCallbackInfo *callback_info;

		vfunc_info = g_interface_info_get_vfunc (info, i);
		vfunc_name = g_base_info_get_name (vfunc_info);

		/* FIXME: g_vfunc_info_get_offset does not seem to work here. */
		field_info = get_field_info (struct_info, vfunc_name);
		g_assert (field_info);
		field_offset = g_field_info_get_offset (field_info);
		field_type_info = g_field_info_get_type (field_info);

		perl_method_name = g_ascii_strup (vfunc_name, -1);
		callback_info = create_perl_callback_closure_for_named_sub (
		                  field_type_info, perl_method_name);
		dwarn ("installing vfunc %s as %s at offset %d (vs. %d) inside %p\n",
		       vfunc_name, perl_method_name,
		       field_offset, g_vfunc_info_get_offset (vfunc_info),
		       iface);
		G_STRUCT_MEMBER (gpointer, iface, field_offset) = callback_info->closure;

		g_base_info_unref (field_type_info);
		g_base_info_unref (field_info);
		g_base_info_unref (vfunc_info);
	}
	g_base_info_unref (struct_info);
}
예제 #3
0
VALUE
rb_gi_field_info_get_field_raw(GIFieldInfo *info, gpointer memory)
{
    GIArgument argument;
    GITypeInfo *type_info;
    GITypeTag type_tag;
    VALUE rb_field_value;

    type_info = g_field_info_get_type(info);
    type_tag = g_type_info_get_tag(type_info);

    if (!g_field_info_get_field(info, memory, &argument)) {
        g_base_info_unref(type_info);
        rb_raise(rb_eArgError, "failed to get field value: %s[%s]",
                 g_base_info_get_name(info),
                 g_type_tag_to_string(type_tag));
    }

    if (type_tag == GI_TYPE_TAG_UTF8) {
        int offset;
        offset = g_field_info_get_offset(info);
        argument.v_string = G_STRUCT_MEMBER(gchar *, memory, offset);
    }
예제 #4
0
파일: boxed.c 프로젝트: Katyunechka/gjs
/* Check if the type of the boxed is "simple" - every field is a non-pointer
 * type that we know how to assign to. If so, then we can allocate and free
 * instances without needing a constructor.
 */
static gboolean
struct_is_simple(GIStructInfo *info)
{
    int n_fields = g_struct_info_get_n_fields(info);
    gboolean is_simple = TRUE;
    int i;

    /* If it's opaque, it's not simple */
    if (n_fields == 0)
        return FALSE;

    for (i = 0; i < n_fields && is_simple; i++) {
        GIFieldInfo *field_info = g_struct_info_get_field(info, i);
        GITypeInfo *type_info = g_field_info_get_type(field_info);

        is_simple = type_can_be_allocated_directly(type_info);

        g_base_info_unref((GIBaseInfo *)field_info);
        g_base_info_unref((GIBaseInfo *)type_info);
    }

    return is_simple;
}
static void
create_native_closure (GType            interface_type,
                       GIInterfaceInfo *iface_info,
                       GIVFuncInfo     *vfunc_info,
                       MethodImpl      *impl)
{
  GIFunctionInfo *invoker_info;
  GIStructInfo *struct_info;
  GIFieldInfo *field_info;
  GITypeInfo *type_info;
  GICallbackInfo *callback_info;
  guint n_fields, i;
  gboolean found_field_info;

  invoker_info = g_vfunc_info_get_invoker (vfunc_info);
  if (invoker_info == NULL)
    {
      g_debug ("No invoker for VFunc '%s.%s'",
               g_base_info_get_name (iface_info),
               g_base_info_get_name (vfunc_info));
      return;
    }

  struct_info = g_interface_info_get_iface_struct (iface_info);
  n_fields = g_struct_info_get_n_fields (struct_info);

  found_field_info = FALSE;
  for (i = 0; i < n_fields; i++)
    {
      field_info = g_struct_info_get_field (struct_info, i);

      if (strcmp (g_base_info_get_name (field_info),
                  g_base_info_get_name (vfunc_info)) == 0)
        {
          found_field_info = TRUE;
          break;
        }

      g_base_info_unref (field_info);
    }

  if (!found_field_info)
    {
      g_debug ("No struct field for VFunc '%s.%s'",
               g_base_info_get_name (iface_info),
               g_base_info_get_name (vfunc_info));
      g_base_info_unref (struct_info);
      g_base_info_unref (invoker_info);
      return;
    }

  type_info = g_field_info_get_type (field_info);
  g_assert (g_type_info_get_tag (type_info) == GI_TYPE_TAG_INTERFACE);

  callback_info = g_type_info_get_interface (type_info);
  g_assert (g_base_info_get_type (callback_info) == GI_INFO_TYPE_CALLBACK);

  impl->interface_type = interface_type;
  impl->invoker_info = invoker_info;
  impl->method_name = g_base_info_get_name (invoker_info);
  impl->closure = g_callable_info_prepare_closure (callback_info, &impl->cif,
                                                   handle_method_impl, impl);
  impl->struct_offset = g_field_info_get_offset (field_info);

  g_base_info_unref (callback_info);
  g_base_info_unref (type_info);
  g_base_info_unref (field_info);
  g_base_info_unref (struct_info);
}
예제 #6
0
gboolean
pygi_g_struct_info_is_simple (GIStructInfo *struct_info)
{
    gboolean is_simple;
    gsize n_field_infos;
    gsize i;

    is_simple = TRUE;

    n_field_infos = g_struct_info_get_n_fields (struct_info);

    for (i = 0; i < n_field_infos && is_simple; i++) {
        GIFieldInfo *field_info;
        GITypeInfo *field_type_info;
		GITypeTag field_type_tag;
        field_info = g_struct_info_get_field (struct_info, i);
        field_type_info = g_field_info_get_type (field_info);

        

        field_type_tag = g_type_info_get_tag (field_type_info);

        switch (field_type_tag) {
            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_UNICHAR:
                if (g_type_info_is_pointer (field_type_info)) {
                    is_simple = FALSE;
                }
                break;
            case GI_TYPE_TAG_VOID:
            case GI_TYPE_TAG_GTYPE:
            case GI_TYPE_TAG_ERROR:
            case GI_TYPE_TAG_UTF8:
            case GI_TYPE_TAG_FILENAME:
            case GI_TYPE_TAG_ARRAY:
            case GI_TYPE_TAG_GLIST:
            case GI_TYPE_TAG_GSLIST:
            case GI_TYPE_TAG_GHASH:
                is_simple = FALSE;
                break;
            case GI_TYPE_TAG_INTERFACE:
            {
                GIBaseInfo *info;
                GIInfoType info_type;

                info = g_type_info_get_interface (field_type_info);
                info_type = g_base_info_get_type (info);

                switch (info_type) {
                    case GI_INFO_TYPE_STRUCT:
                        if (g_type_info_is_pointer (field_type_info)) {
                            is_simple = FALSE;
                        } else {
                            is_simple = pygi_g_struct_info_is_simple ( (GIStructInfo *) info);
                        }
                        break;
                    case GI_INFO_TYPE_UNION:
                        /* TODO */
                        is_simple = FALSE;
                        break;
                    case GI_INFO_TYPE_ENUM:
                    case GI_INFO_TYPE_FLAGS:
                        if (g_type_info_is_pointer (field_type_info)) {
                            is_simple = FALSE;
                        }
                        break;
                    case GI_INFO_TYPE_BOXED:
                    case GI_INFO_TYPE_OBJECT:
                    case GI_INFO_TYPE_CALLBACK:
                    case GI_INFO_TYPE_INTERFACE:
                        is_simple = FALSE;
                        break;
                    case GI_INFO_TYPE_VFUNC:
                    case GI_INFO_TYPE_INVALID:
                    case GI_INFO_TYPE_FUNCTION:
                    case GI_INFO_TYPE_CONSTANT:
                    case GI_INFO_TYPE_VALUE:
                    case GI_INFO_TYPE_SIGNAL:
                    case GI_INFO_TYPE_PROPERTY:
                    case GI_INFO_TYPE_FIELD:
                    case GI_INFO_TYPE_ARG:
                    case GI_INFO_TYPE_TYPE:
                    case GI_INFO_TYPE_UNRESOLVED:
                    default:
                        g_assert_not_reached();
                        break;
                }

                g_base_info_unref (info);
                break;
            }
        }

        g_base_info_unref ( (GIBaseInfo *) field_type_info);
        g_base_info_unref ( (GIBaseInfo *) field_info);
    }

    return is_simple;
}
예제 #7
0
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;
}
예제 #8
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;
}
예제 #9
0
파일: boxed.c 프로젝트: Katyunechka/gjs
static JSBool
boxed_set_field_from_value(JSContext   *context,
                           Boxed       *priv,
                           GIFieldInfo *field_info,
                           jsval        value)
{
    GITypeInfo *type_info;
    GArgument arg;
    gboolean success = FALSE;
    gboolean need_release = FALSE;

    type_info = g_field_info_get_type (field_info);

    if (!g_type_info_is_pointer (type_info) &&
        g_type_info_get_tag (type_info) == GI_TYPE_TAG_INTERFACE) {

        GIBaseInfo *interface_info = g_type_info_get_interface(type_info);

        if (g_base_info_get_type (interface_info) == GI_INFO_TYPE_STRUCT ||
            g_base_info_get_type (interface_info) == GI_INFO_TYPE_BOXED) {

            success = set_nested_interface_object (context, priv,
                                                   field_info, type_info,
                                                   interface_info, value);

            g_base_info_unref ((GIBaseInfo *)interface_info);

            goto out;
        }

        g_base_info_unref ((GIBaseInfo *)interface_info);

    }

    if (!gjs_value_to_g_argument(context, value,
                                 type_info,
                                 g_base_info_get_name ((GIBaseInfo *)field_info),
                                 GJS_ARGUMENT_FIELD,
                                 GI_TRANSFER_NOTHING,
                                 TRUE, &arg))
        goto out;

    need_release = TRUE;

    if (!g_field_info_set_field (field_info, priv->gboxed, &arg)) {
        gjs_throw(context, "Writing field %s.%s is not supported",
                  g_base_info_get_name ((GIBaseInfo *)priv->info),
                  g_base_info_get_name ((GIBaseInfo *)field_info));
        goto out;
    }

    success = TRUE;

out:
    if (need_release)
        gjs_g_argument_release (context, GI_TRANSFER_NOTHING,
                                type_info,
                                &arg);

    g_base_info_unref ((GIBaseInfo *)type_info);

    return success;
}
예제 #10
0
파일: boxed.c 프로젝트: Katyunechka/gjs
static JSBool
boxed_field_getter (JSContext *context,
                    JSObject  *obj,
                    jsid       id,
                    jsval     *value)
{
    Boxed *priv;
    GIFieldInfo *field_info;
    GITypeInfo *type_info;
    GArgument arg;
    gboolean success = FALSE;

    priv = priv_from_js(context, obj);
    if (!priv)
        return JS_FALSE;

    field_info = get_field_info(context, priv, id);
    if (!field_info)
        return JS_FALSE;

    type_info = g_field_info_get_type (field_info);

    if (priv->gboxed == NULL) { /* direct access to proto field */
        gjs_throw(context, "Can't get field %s.%s from a prototype",
                  g_base_info_get_name ((GIBaseInfo *)priv->info),
                  g_base_info_get_name ((GIBaseInfo *)field_info));
        goto out;
    }

    if (!g_type_info_is_pointer (type_info) &&
        g_type_info_get_tag (type_info) == GI_TYPE_TAG_INTERFACE) {

        GIBaseInfo *interface_info = g_type_info_get_interface(type_info);

        if (g_base_info_get_type (interface_info) == GI_INFO_TYPE_STRUCT ||
            g_base_info_get_type (interface_info) == GI_INFO_TYPE_BOXED) {

            success = get_nested_interface_object (context, obj, priv,
                                                   field_info, type_info, interface_info,
                                                   value);

            g_base_info_unref ((GIBaseInfo *)interface_info);

            goto out;
        }

        g_base_info_unref ((GIBaseInfo *)interface_info);
    }

    if (!g_field_info_get_field (field_info, priv->gboxed, &arg)) {
        gjs_throw(context, "Reading field %s.%s is not supported",
                  g_base_info_get_name ((GIBaseInfo *)priv->info),
                  g_base_info_get_name ((GIBaseInfo *)field_info));
        goto out;
    }

    if (!gjs_value_from_g_argument (context, value,
                                    type_info,
                                    &arg,
                                    TRUE))
        goto out;

    success = TRUE;

out:
    g_base_info_unref ((GIBaseInfo *)field_info);
    g_base_info_unref ((GIBaseInfo *)type_info);

    return success;
}
예제 #11
0
/**
 * g_field_info_set_field:
 * @field_info: a #GIFieldInfo
 * @mem: pointer to a block of memory representing a C structure or union
 * @value: a #GArgument holding the value to store
 *
 * Writes a field identified by a #GFieldInfo to a C structure or
 * union.  This only handles fields of simple C types. It will fail
 * for a field of a composite type like a nested structure or union
 * even if that is actually writable. Note also that that it will refuse
 * to write fields where memory management would by required. A field
 * with a type such as 'char *' must be set with a setter function.
 *
 * Returns: %TRUE if writing the field succeeded, otherwise %FALSE
 */
gboolean
g_field_info_set_field (GIFieldInfo     *field_info,
			gpointer         mem,
			const GArgument *value)
{
    int offset;
    GITypeInfo *type_info;
    gboolean result = FALSE;

    if ((g_field_info_get_flags (field_info) & GI_FIELD_IS_WRITABLE) == 0)
      return FALSE;

    offset = g_field_info_get_offset (field_info);
    type_info = g_field_info_get_type (field_info);

    if (!g_type_info_is_pointer (type_info))
      {
	switch (g_type_info_get_tag (type_info))
	  {
	  case GI_TYPE_TAG_VOID:
	    g_warning("Field %s: should not be have void type",
		      g_base_info_get_name ((GIBaseInfo *)field_info));
	    break;
	  case GI_TYPE_TAG_BOOLEAN:
	    G_STRUCT_MEMBER(gboolean, mem, offset) = value->v_boolean != FALSE;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT8:
	  case GI_TYPE_TAG_UINT8:
	    G_STRUCT_MEMBER(guint8, mem, offset) = value->v_uint8;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT16:
	  case GI_TYPE_TAG_UINT16:
	  case GI_TYPE_TAG_SHORT:
	  case GI_TYPE_TAG_USHORT:
	    G_STRUCT_MEMBER(guint16, mem, offset) = value->v_uint16;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT32:
	  case GI_TYPE_TAG_UINT32:
	  case GI_TYPE_TAG_INT:
	  case GI_TYPE_TAG_UINT:
	    G_STRUCT_MEMBER(guint32, mem, offset) = value->v_uint32;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT64:
	  case GI_TYPE_TAG_UINT64:
	    G_STRUCT_MEMBER(guint64, mem, offset) = value->v_uint64;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_LONG:
	  case GI_TYPE_TAG_ULONG:
	    G_STRUCT_MEMBER(gulong, mem, offset)= value->v_ulong;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_SSIZE:
	  case GI_TYPE_TAG_SIZE:
	  case GI_TYPE_TAG_GTYPE:
	    G_STRUCT_MEMBER(gsize, mem, offset) = value->v_size;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_FLOAT:
	    G_STRUCT_MEMBER(gfloat, mem, offset) = value->v_float;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_DOUBLE:
	    G_STRUCT_MEMBER(gdouble, mem, offset)= value->v_double;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_TIME_T:
#if SIZEOF_TIME_T == 4
            G_STRUCT_MEMBER(time_t, mem, offset) = value->v_int32;
#elif SIZEOF_TIME_T == 8
            G_STRUCT_MEMBER(time_t, mem, offset) = value->v_int64;
#else
#  error "Unexpected size for time_t: not 4 or 8"
#endif
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_UTF8:
	  case GI_TYPE_TAG_FILENAME:
	  case GI_TYPE_TAG_ARRAY:
	  case GI_TYPE_TAG_GLIST:
	  case GI_TYPE_TAG_GSLIST:
	  case GI_TYPE_TAG_GHASH:
	    g_warning("Field %s: type %s should have is_pointer set",
		      g_base_info_get_name ((GIBaseInfo *)field_info),
		      g_type_tag_to_string (g_type_info_get_tag (type_info)));
	    break;
	  case GI_TYPE_TAG_ERROR:
	    /* Needs to be handled by the language binding directly */
	    break;
	  case GI_TYPE_TAG_INTERFACE:
	    {
	      GIBaseInfo *interface = g_type_info_get_interface (type_info);
	      switch (g_base_info_get_type (interface))
		{
		case GI_INFO_TYPE_STRUCT:
		case GI_INFO_TYPE_UNION:
		case GI_INFO_TYPE_BOXED:
		  /* Needs to be handled by the language binding directly */
		  break;
		case GI_INFO_TYPE_OBJECT:
		  break;
		case GI_INFO_TYPE_ENUM:
		case GI_INFO_TYPE_FLAGS:
		  {
		    /* See FIXME above
		     */
		    GITypeTag storage_type = g_enum_info_get_storage_type ((GIEnumInfo *)interface);
		    switch (storage_type)
		      {
		      case GI_TYPE_TAG_INT8:
		      case GI_TYPE_TAG_UINT8:
			G_STRUCT_MEMBER(guint8, mem, offset) = (guint8)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT16:
		      case GI_TYPE_TAG_UINT16:
		      case GI_TYPE_TAG_SHORT:
		      case GI_TYPE_TAG_USHORT:
			G_STRUCT_MEMBER(guint16, mem, offset) = (guint16)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT32:
		      case GI_TYPE_TAG_UINT32:
		      case GI_TYPE_TAG_INT:
		      case GI_TYPE_TAG_UINT:
			G_STRUCT_MEMBER(guint32, mem, offset) = (guint32)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT64:
		      case GI_TYPE_TAG_UINT64:
			G_STRUCT_MEMBER(guint64, mem, offset) = (guint64)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_LONG:
		      case GI_TYPE_TAG_ULONG:
			G_STRUCT_MEMBER(gulong, mem, offset) = (gulong)value->v_int;
			result = TRUE;
			break;
		      default:
			g_warning("Field %s: Unexpected enum storage type %s",
				  g_base_info_get_name ((GIBaseInfo *)field_info),
				  g_type_tag_to_string (storage_type));
			break;
		      }
		    break;
		  }
		  break;
		case GI_INFO_TYPE_VFUNC:
		case GI_INFO_TYPE_CALLBACK:
		  g_warning("Field%s: Interface type %d should have is_pointer set",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		case GI_INFO_TYPE_INVALID:
		case GI_INFO_TYPE_INTERFACE:
		case GI_INFO_TYPE_FUNCTION:
		case GI_INFO_TYPE_CONSTANT:
		case GI_INFO_TYPE_ERROR_DOMAIN:
		case GI_INFO_TYPE_VALUE:
		case GI_INFO_TYPE_SIGNAL:
		case GI_INFO_TYPE_PROPERTY:
		case GI_INFO_TYPE_FIELD:
		case GI_INFO_TYPE_ARG:
		case GI_INFO_TYPE_TYPE:
		case GI_INFO_TYPE_UNRESOLVED:
		  g_warning("Field %s: Interface type %d not expected",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		}

	      g_base_info_unref ((GIBaseInfo *)interface);
	      break;
	    }
	    break;
	  }
      }

    g_base_info_unref ((GIBaseInfo *)type_info);

    return result;
}
예제 #12
0
/**
 * g_field_info_get_field:
 * @field_info: a #GIFieldInfo
 * @mem: pointer to a block of memory representing a C structure or union
 * @value: a #GArgument into which to store the value retrieved
 *
 * Reads a field identified by a #GFieldInfo from a C structure or
 * union.  This only handles fields of simple C types. It will fail
 * for a field of a composite type like a nested structure or union
 * even if that is actually readable.
 *
 * Returns: %TRUE if reading the field succeeded, otherwise %FALSE
 */
gboolean
g_field_info_get_field (GIFieldInfo *field_info,
			gpointer     mem,
			GArgument   *value)
{
    int offset;
    GITypeInfo *type_info;
    gboolean result = FALSE;

    if ((g_field_info_get_flags (field_info) & GI_FIELD_IS_READABLE) == 0)
      return FALSE;

    offset = g_field_info_get_offset (field_info);
    type_info = g_field_info_get_type (field_info);

    if (g_type_info_is_pointer (type_info))
      {
	value->v_pointer = G_STRUCT_MEMBER(gpointer, mem, offset);
	result = TRUE;
      }
    else
      {
	switch (g_type_info_get_tag (type_info))
	  {
	  case GI_TYPE_TAG_VOID:
	    g_warning("Field %s: should not be have void type",
		      g_base_info_get_name ((GIBaseInfo *)field_info));
	    break;
	  case GI_TYPE_TAG_BOOLEAN:
	    value->v_boolean = G_STRUCT_MEMBER(gboolean, mem, offset) != FALSE;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT8:
	  case GI_TYPE_TAG_UINT8:
	    value->v_uint8 = G_STRUCT_MEMBER(guint8, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT16:
	  case GI_TYPE_TAG_UINT16:
	  case GI_TYPE_TAG_SHORT:
	  case GI_TYPE_TAG_USHORT:
	    value->v_uint16 = G_STRUCT_MEMBER(guint16, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT32:
	  case GI_TYPE_TAG_UINT32:
	  case GI_TYPE_TAG_INT:
	  case GI_TYPE_TAG_UINT:
	    value->v_uint32 = G_STRUCT_MEMBER(guint32, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT64:
	  case GI_TYPE_TAG_UINT64:
	    value->v_uint64 = G_STRUCT_MEMBER(guint64, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_LONG:
	  case GI_TYPE_TAG_ULONG:
	    value->v_ulong = G_STRUCT_MEMBER(gulong, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_SSIZE:
	  case GI_TYPE_TAG_SIZE:
	  case GI_TYPE_TAG_GTYPE:
	    value->v_size = G_STRUCT_MEMBER(gsize, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_FLOAT:
	    value->v_float = G_STRUCT_MEMBER(gfloat, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_DOUBLE:
	    value->v_double = G_STRUCT_MEMBER(gdouble, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_TIME_T:
#if SIZEOF_TIME_T == 4
	    value->v_int32 = G_STRUCT_MEMBER(time_t, mem, offset);
#elif SIZEOF_TIME_T == 8
	    value->v_int64 = G_STRUCT_MEMBER(time_t, mem, offset);
#else
#  error "Unexpected size for time_t: not 4 or 8"
#endif
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_UTF8:
	  case GI_TYPE_TAG_FILENAME:
	  case GI_TYPE_TAG_ARRAY:
	  case GI_TYPE_TAG_GLIST:
	  case GI_TYPE_TAG_GSLIST:
	  case GI_TYPE_TAG_GHASH:
	    g_warning("Field %s: type %s should have is_pointer set",
		      g_base_info_get_name ((GIBaseInfo *)field_info),
		      g_type_tag_to_string (g_type_info_get_tag (type_info)));
	    break;
	  case GI_TYPE_TAG_ERROR:
	    /* Needs to be handled by the language binding directly */
	    break;
	  case GI_TYPE_TAG_INTERFACE:
	    {
	      GIBaseInfo *interface = g_type_info_get_interface (type_info);
	      switch (g_base_info_get_type (interface))
		{
		case GI_INFO_TYPE_STRUCT:
		case GI_INFO_TYPE_UNION:
		case GI_INFO_TYPE_BOXED:
		  /* Needs to be handled by the language binding directly */
		  break;
		case GI_INFO_TYPE_OBJECT:
		  break;
		case GI_INFO_TYPE_ENUM:
		case GI_INFO_TYPE_FLAGS:
		  {
		    /* FIXME: there's a mismatch here between the value->v_int we use
		     * here and the glong result returned from g_value_info_get_value().
		     * But to switch this to glong, we'd have to make g_function_info_invoke()
		     * translate value->v_long to the proper ABI for an enum function
		     * call parameter, which will usually be int, and then fix up language
		     * bindings.
		     */
		    GITypeTag storage_type = g_enum_info_get_storage_type ((GIEnumInfo *)interface);
		    switch (storage_type)
		      {
		      case GI_TYPE_TAG_INT8:
		      case GI_TYPE_TAG_UINT8:
			value->v_int = (gint)G_STRUCT_MEMBER(guint8, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT16:
		      case GI_TYPE_TAG_UINT16:
		      case GI_TYPE_TAG_SHORT:
		      case GI_TYPE_TAG_USHORT:
			value->v_int = (gint)G_STRUCT_MEMBER(guint16, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT32:
		      case GI_TYPE_TAG_UINT32:
		      case GI_TYPE_TAG_INT:
		      case GI_TYPE_TAG_UINT:
			value->v_int = (gint)G_STRUCT_MEMBER(guint32, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT64:
		      case GI_TYPE_TAG_UINT64:
			value->v_int = (gint)G_STRUCT_MEMBER(guint64, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_LONG:
		      case GI_TYPE_TAG_ULONG:
			value->v_int = (gint)G_STRUCT_MEMBER(gulong, mem, offset);
			result = TRUE;
			break;
		      default:
			g_warning("Field %s: Unexpected enum storage type %s",
				  g_base_info_get_name ((GIBaseInfo *)field_info),
				  g_type_tag_to_string (storage_type));
			break;
		      }
		    break;
		  }
		case GI_INFO_TYPE_VFUNC:
		case GI_INFO_TYPE_CALLBACK:
		  g_warning("Field %s: Interface type %d should have is_pointer set",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		case GI_INFO_TYPE_INVALID:
		case GI_INFO_TYPE_INTERFACE:
		case GI_INFO_TYPE_FUNCTION:
		case GI_INFO_TYPE_CONSTANT:
		case GI_INFO_TYPE_ERROR_DOMAIN:
		case GI_INFO_TYPE_VALUE:
		case GI_INFO_TYPE_SIGNAL:
		case GI_INFO_TYPE_PROPERTY:
		case GI_INFO_TYPE_FIELD:
		case GI_INFO_TYPE_ARG:
		case GI_INFO_TYPE_TYPE:
		case GI_INFO_TYPE_UNRESOLVED:
		  g_warning("Field %s: Interface type %d not expected",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		}

	      g_base_info_unref ((GIBaseInfo *)interface);
	      break;
	    }
	    break;
	  }
      }

    g_base_info_unref ((GIBaseInfo *)type_info);

    return result;
}
예제 #13
0
파일: marshal.c 프로젝트: ntd/lgi
int
lgi_marshal_field (lua_State *L, gpointer object, gboolean getmode,
		   int parent_arg, int field_arg, int val_arg)
{
  GITypeInfo *ti;
  int to_remove, nret;

  /* Check the type of the field information. */
  if (lgi_udata_test (L, field_arg, LGI_GI_INFO))
    {
      GIFieldInfo **fi = lua_touserdata (L, field_arg);
      GIFieldInfoFlags flags;

      /* Check, whether field is readable/writable. */
      flags = g_field_info_get_flags (*fi);
      if ((flags & (getmode ? GI_FIELD_IS_READABLE
			: GI_FIELD_IS_WRITABLE)) == 0)
	{
	  /* Check,  whether  parent  did not  disable  access  checks
	     completely. */
	  lua_getfield (L, -1, "_allow");
	  if (!lua_toboolean (L, -1))
	    {
	      /* Prepare proper error message. */
	      lua_concat (L,
			  lgi_type_get_name (L,
					     g_base_info_get_container (*fi)));
	      return luaL_error (L, "%s: field `%s' is not %s",
				 lua_tostring (L, -1),
				 g_base_info_get_name (*fi),
				 getmode ? "readable" : "writable");
	    }
	  lua_pop (L, 1);
	}

      /* Map GIArgument to proper memory location, get typeinfo of the
	 field and perform actual marshalling. */
      object = (char *) object + g_field_info_get_offset (*fi);
      ti = g_field_info_get_type (*fi);
      lgi_gi_info_new (L, ti);
      to_remove = lua_gettop (L);
    }
  else
    {
      /* Consult field table, get kind of field and offset. */
      int kind;
      lgi_makeabs (L, field_arg);
      luaL_checktype (L, field_arg, LUA_TTABLE);
      lua_rawgeti (L, field_arg, 1);
      object = (char *) object + lua_tointeger (L, -1);
      lua_rawgeti (L, field_arg, 2);
      kind = lua_tonumber (L, -1);
      lua_pop (L, 2);

      /* Load type information from the table and decide how to handle
	 it according to 'kind' */
      lua_rawgeti (L, field_arg, 3);
      switch (kind)
	{
	case 0:
	  /* field[3] contains typeinfo, load it and fall through. */
	  ti = *(GITypeInfo **) luaL_checkudata (L, -1, LGI_GI_INFO);
	  to_remove = lua_gettop (L);
	  break;

	case 1:
	case 2:
	  {
	    GIArgument *arg = (GIArgument *) object;
	    if (getmode)
	      {
		if (kind == 1)
		  {
		    object = arg->v_pointer;
		    parent_arg = 0;
		  }
		lgi_record_2lua (L, object, FALSE, parent_arg);
		return 1;
	      }
	    else
	      {
		g_assert (kind == 1);
		lgi_record_2c (L, val_arg, arg->v_pointer,
			       FALSE, TRUE, FALSE, FALSE);
		return 0;
	      }
	    break;
	  }

	case 3:
	  {
	    /* Get the typeinfo for marshalling the numeric enum value. */
	    lua_rawgeti (L, field_arg, 4);
	    ti = *(GITypeInfo **) luaL_checkudata (L, -1, LGI_GI_INFO);
	    if (getmode)
	      {
		/* Use typeinfo to unmarshal numeric value. */
		lgi_marshal_2lua (L, ti, NULL, GI_DIRECTION_OUT,
				  GI_TRANSFER_NOTHING, object, 0,
				  NULL, NULL);

		/* Replace numeric field with symbolic value. */
		lua_gettable (L, -3);
		lua_replace (L, -3);
		lua_pop (L, 1);
		return 1;
	      }
	    else
	      {
		/* Convert enum symbol to numeric value. */
		if (lua_type (L, val_arg != LUA_TNUMBER))
		  {
		    lua_pushvalue (L, -1);
		    lua_pushvalue (L, val_arg);
		    lua_call (L, 1, 1);
		    lua_replace (L, val_arg);
		  }

		/* Use typeinfo to marshal the numeric value. */
		lgi_marshal_2c (L, ti, NULL, GI_TRANSFER_NOTHING, object,
				val_arg, 0, NULL, NULL);
		lua_pop (L, 2);
		return 0;
	      }
	  }

	default:
	  return luaL_error (L, "field has bad kind %d", kind);
	}
    }

  if (getmode)
    {
      lgi_marshal_2lua (L, ti, NULL, GI_DIRECTION_OUT, GI_TRANSFER_NOTHING,
			object, parent_arg, NULL, NULL);
      nret = 1;
    }
  else
    {
      lgi_marshal_2c (L, ti, NULL, GI_TRANSFER_EVERYTHING, object, val_arg,
		      0, NULL, NULL);
      nret = 0;
    }

  lua_remove (L, to_remove);
  return nret;
}
예제 #14
0
파일: param.c 프로젝트: goizueta/gjs
/* a hook on getting a property; set value_p to override property's value.
 * Return value is JS_FALSE on OOM/exception.
 */
static JSBool
param_get_prop(JSContext *context,
               JSObject  *obj,
               jsid       id,
               jsval     *value_p)
{
    JSBool success;
    Param *priv;
    GParamSpec *pspec;
    char *name;
    GType gtype;
    GIObjectInfo *info = NULL, *parent_info = NULL;
    GIFieldInfo *field_info = NULL;
    GITypeInfo *type_info = NULL;
    GIArgument arg;

    if (!gjs_get_string_id(context, id, &name))
        return JS_TRUE; /* not something we affect, but no error */

    priv = priv_from_js(context, obj);

    if (priv == NULL) {
        g_free(name);
        return JS_FALSE; /* wrong class */
    }

    success = JS_FALSE;
    pspec = priv->gparam;

    gtype = G_TYPE_FROM_INSTANCE(pspec);
    info = (GIObjectInfo*)g_irepository_find_by_gtype(g_irepository_get_default(), gtype);

    if (info == NULL) {
        /* We may have a non-introspectable GParamSpec subclass here. Just return VOID. */
        *value_p = JSVAL_VOID;
        success = JS_TRUE;
        goto out;
    }

    parent_info = g_object_info_get_parent(info);

    field_info = find_field_info(info, name);

    if (field_info == NULL) {
        /* Try it on the parent GParamSpec for generic GParamSpec properties. */
        field_info = find_field_info(parent_info, name);
    }

    if (field_info == NULL) {
        *value_p = JSVAL_VOID;
        success = JS_TRUE;
        goto out;
    }

    type_info = g_field_info_get_type(field_info);

    if (!g_field_info_get_field(field_info, priv->gparam, &arg)) {
        gjs_throw(context, "Reading field %s.%s is not supported",
                  g_base_info_get_name(info),
                  g_base_info_get_name((GIBaseInfo*)field_info));
        goto out;
    }

    if (!gjs_value_from_g_argument(context, value_p, type_info, &arg, TRUE))
        goto out;

    success = JS_TRUE;

 out:
    if (field_info != NULL)
        g_base_info_unref((GIBaseInfo*)field_info);
    if (type_info != NULL)
        g_base_info_unref((GIBaseInfo*)type_info);
    if (info != NULL)
        g_base_info_unref((GIBaseInfo*)info);
    if (parent_info != NULL)
        g_base_info_unref((GIBaseInfo*)parent_info);
    g_free(name);

    return success;
}
예제 #15
0
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;
}