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); }
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); }
/* 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); }
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; }
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; }
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; }
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; }
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; }
/** * 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; }
/** * 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; }
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; }
/* 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; }
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; }