static void rb_gi_argument_from_ruby_array_c(GIArgument *argument, G_GNUC_UNUSED GITypeInfo *type_info, GITypeInfo *element_type_info, VALUE rb_argument) { GITypeTag element_type_tag; element_type_tag = g_type_info_get_tag(element_type_info); switch (element_type_tag) { case GI_TYPE_TAG_VOID: case GI_TYPE_TAG_BOOLEAN: rb_raise(rb_eNotImpError, "TODO: Ruby -> GIArgument(array)[%s]", g_type_tag_to_string(element_type_tag)); break; case GI_TYPE_TAG_INT8: argument->v_pointer = StringValueCStr(rb_argument); break; case GI_TYPE_TAG_UINT8: argument->v_pointer = RSTRING_PTR(rb_argument); break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: case GI_TYPE_TAG_FLOAT: case GI_TYPE_TAG_DOUBLE: case GI_TYPE_TAG_GTYPE: rb_raise(rb_eNotImpError, "TODO: Ruby -> GIArgument(array)[%s]", g_type_tag_to_string(element_type_tag)); break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: argument->v_pointer = RVAL2STRV(rb_argument); break; case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_INTERFACE: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_ERROR: case GI_TYPE_TAG_UNICHAR: rb_raise(rb_eNotImpError, "TODO: Ruby -> GIArgument(array)[%s]", g_type_tag_to_string(element_type_tag)); break; default: g_assert_not_reached(); break; } }
static gboolean gi_argument_to_c_long (GIArgument *arg_in, long *c_long_out, GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_INT8: *c_long_out = arg_in->v_int8; return TRUE; case GI_TYPE_TAG_UINT8: *c_long_out = arg_in->v_uint8; return TRUE; case GI_TYPE_TAG_INT16: *c_long_out = arg_in->v_int16; return TRUE; case GI_TYPE_TAG_UINT16: *c_long_out = arg_in->v_uint16; return TRUE; case GI_TYPE_TAG_INT32: *c_long_out = arg_in->v_int32; return TRUE; case GI_TYPE_TAG_UINT32: *c_long_out = arg_in->v_uint32; return TRUE; case GI_TYPE_TAG_INT64: if (arg_in->v_int64 > G_MAXLONG || arg_in->v_int64 < G_MINLONG) { PyErr_Format (PyExc_TypeError, "Unable to marshal %s to C long", g_type_tag_to_string(type_tag)); return FALSE; } *c_long_out = (glong)arg_in->v_int64; return TRUE; case GI_TYPE_TAG_UINT64: if (arg_in->v_uint64 > G_MAXLONG) { PyErr_Format (PyExc_TypeError, "Unable to marshal %s to C long", g_type_tag_to_string(type_tag)); return FALSE; } *c_long_out = (glong)arg_in->v_uint64; return TRUE; default: PyErr_Format (PyExc_TypeError, "Unable to marshal %s to C long", g_type_tag_to_string (type_tag)); return FALSE; } }
void _pygi_hash_pointer_to_arg (GIArgument *arg, GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_INT8: arg->v_int8 = GPOINTER_TO_INT (arg->v_pointer); break; case GI_TYPE_TAG_INT16: arg->v_int16 = GPOINTER_TO_INT (arg->v_pointer); break; case GI_TYPE_TAG_INT32: arg->v_int32 = GPOINTER_TO_INT (arg->v_pointer); break; case GI_TYPE_TAG_UINT8: arg->v_uint8 = GPOINTER_TO_UINT (arg->v_pointer); break; case GI_TYPE_TAG_UINT16: arg->v_uint16 = GPOINTER_TO_UINT (arg->v_pointer); break; case GI_TYPE_TAG_UINT32: arg->v_uint32 = GPOINTER_TO_UINT (arg->v_pointer); break; case GI_TYPE_TAG_GTYPE: arg->v_size = GPOINTER_TO_SIZE (arg->v_pointer); break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_INTERFACE: break; default: g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag)); } }
gpointer _pygi_arg_to_hash_pointer (const GIArgument *arg, GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_INT8: return GINT_TO_POINTER (arg->v_int8); case GI_TYPE_TAG_UINT8: return GINT_TO_POINTER (arg->v_uint8); case GI_TYPE_TAG_INT16: return GINT_TO_POINTER (arg->v_int16); case GI_TYPE_TAG_UINT16: return GINT_TO_POINTER (arg->v_uint16); case GI_TYPE_TAG_INT32: return GINT_TO_POINTER (arg->v_int32); case GI_TYPE_TAG_UINT32: return GINT_TO_POINTER (arg->v_uint32); case GI_TYPE_TAG_GTYPE: return GSIZE_TO_POINTER (arg->v_size); case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_INTERFACE: return arg->v_pointer; default: g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag)); return arg->v_pointer; } }
gsize _pygi_g_type_tag_size (GITypeTag type_tag) { gsize size = 0; switch (type_tag) { case GI_TYPE_TAG_BOOLEAN: size = sizeof (gboolean); break; case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: size = sizeof (gint8); break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: size = sizeof (gint16); break; case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: size = sizeof (gint32); break; case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: size = sizeof (gint64); break; case GI_TYPE_TAG_FLOAT: size = sizeof (gfloat); break; case GI_TYPE_TAG_DOUBLE: size = sizeof (gdouble); break; case GI_TYPE_TAG_GTYPE: size = sizeof (GType); break; case GI_TYPE_TAG_UNICHAR: size = sizeof (gunichar); break; case GI_TYPE_TAG_VOID: case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_INTERFACE: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_ERROR: PyErr_Format (PyExc_TypeError, "Unable to know the size (assuming %s is not a pointer)", g_type_tag_to_string (type_tag)); break; } return size; }
static gboolean gi_argument_from_c_long (GIArgument *arg_out, long c_long_in, GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_INT8: arg_out->v_int8 = (gint8)c_long_in; return TRUE; case GI_TYPE_TAG_UINT8: arg_out->v_uint8 = (guint8)c_long_in; return TRUE; case GI_TYPE_TAG_INT16: arg_out->v_int16 = (gint16)c_long_in; return TRUE; case GI_TYPE_TAG_UINT16: arg_out->v_uint16 = (guint16)c_long_in; return TRUE; case GI_TYPE_TAG_INT32: arg_out->v_int32 = (gint32)c_long_in; return TRUE; case GI_TYPE_TAG_UINT32: arg_out->v_uint32 = (guint32)c_long_in; return TRUE; case GI_TYPE_TAG_INT64: arg_out->v_int64 = (gint64)c_long_in; return TRUE; case GI_TYPE_TAG_UINT64: arg_out->v_uint64 = (guint64)c_long_in; return TRUE; default: PyErr_Format (PyExc_TypeError, "Unable to marshal C long %ld to %s", c_long_in, g_type_tag_to_string (type_tag)); return FALSE; } }
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); }
static gboolean gi_argument_to_gsize (GIArgument *arg_in, gsize *gsize_out, GITypeTag type_tag) { switch (type_tag) { case GI_TYPE_TAG_INT8: *gsize_out = arg_in->v_int8; return TRUE; case GI_TYPE_TAG_UINT8: *gsize_out = arg_in->v_uint8; return TRUE; case GI_TYPE_TAG_INT16: *gsize_out = arg_in->v_int16; return TRUE; case GI_TYPE_TAG_UINT16: *gsize_out = arg_in->v_uint16; return TRUE; case GI_TYPE_TAG_INT32: *gsize_out = arg_in->v_int32; return TRUE; case GI_TYPE_TAG_UINT32: *gsize_out = arg_in->v_uint32; return TRUE; case GI_TYPE_TAG_INT64: *gsize_out = arg_in->v_int64; return TRUE; case GI_TYPE_TAG_UINT64: *gsize_out = arg_in->v_uint64; return TRUE; default: PyErr_Format (PyExc_TypeError, "Unable to marshal %s to gsize", g_type_tag_to_string (type_tag)); return FALSE; } }
static gboolean get_enum_size_alignment (GIrNodeEnum *enum_node, gint *size, gint *alignment) { ffi_type *type_ffi; compute_enum_storage_type (enum_node); switch (enum_node->storage_type) { case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_UINT8: type_ffi = &ffi_type_uint8; break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: type_ffi = &ffi_type_uint16; break; case GI_TYPE_TAG_INT32: case GI_TYPE_TAG_UINT32: type_ffi = &ffi_type_uint32; break; case GI_TYPE_TAG_INT64: case GI_TYPE_TAG_UINT64: type_ffi = &ffi_type_uint64; break; default: g_error ("Unexpected enum storage type %s", g_type_tag_to_string (enum_node->storage_type)); } *size = type_ffi->size; *alignment = type_ffi->alignment; return TRUE; }
static void _pygi_closure_convert_ffi_arguments (PyGIInvokeArgState *state, PyGICallableCache *cache, void **args) { gint i; for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) { PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i); if (arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) { state[i].arg_value.v_pointer = * (gpointer *) args[i]; if (state[i].arg_value.v_pointer == NULL) continue; state[i].arg_pointer.v_pointer = state[i].arg_value.v_pointer; state[i].arg_value = *(GIArgument *) state[i].arg_value.v_pointer; continue; } switch (arg_cache->type_tag) { case GI_TYPE_TAG_BOOLEAN: state[i].arg_value.v_boolean = * (gboolean *) args[i]; break; case GI_TYPE_TAG_INT8: state[i].arg_value.v_int8 = * (gint8 *) args[i]; break; case GI_TYPE_TAG_UINT8: state[i].arg_value.v_uint8 = * (guint8 *) args[i]; break; case GI_TYPE_TAG_INT16: state[i].arg_value.v_int16 = * (gint16 *) args[i]; break; case GI_TYPE_TAG_UINT16: state[i].arg_value.v_uint16 = * (guint16 *) args[i]; break; case GI_TYPE_TAG_INT32: state[i].arg_value.v_int32 = * (gint32 *) args[i]; break; case GI_TYPE_TAG_UINT32: state[i].arg_value.v_uint32 = * (guint32 *) args[i]; break; case GI_TYPE_TAG_INT64: state[i].arg_value.v_int64 = * (glong *) args[i]; break; case GI_TYPE_TAG_UINT64: state[i].arg_value.v_uint64 = * (glong *) args[i]; break; case GI_TYPE_TAG_FLOAT: state[i].arg_value.v_float = * (gfloat *) args[i]; break; case GI_TYPE_TAG_DOUBLE: state[i].arg_value.v_double = * (gdouble *) args[i]; break; case GI_TYPE_TAG_UTF8: state[i].arg_value.v_string = * (gchar **) args[i]; break; case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *interface; GIInfoType interface_type; interface = ((PyGIInterfaceCache *) arg_cache)->interface_info; interface_type = g_base_info_get_type (interface); if (interface_type == GI_INFO_TYPE_ENUM) { state[i].arg_value.v_int = * (gint *) args[i]; } else if (interface_type == GI_INFO_TYPE_FLAGS) { state[i].arg_value.v_uint = * (guint *) args[i]; } else { state[i].arg_value.v_pointer = * (gpointer *) args[i]; } break; } case GI_TYPE_TAG_ERROR: case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_ARRAY: case GI_TYPE_TAG_VOID: state[i].arg_value.v_pointer = * (gpointer *) args[i]; break; default: g_warning ("Unhandled type tag %s", g_type_tag_to_string (arg_cache->type_tag)); state[i].arg_value.v_pointer = 0; } } if (cache->throws) { gssize error_index = _pygi_callable_cache_args_len (cache); state[error_index].arg_value.v_pointer = * (gpointer *) args[error_index]; } }
void gy_value_push(GValue * pval, GITypeInfo * info, gy_Object* o) { GITypeTag tag = g_type_info_get_tag(info); GY_DEBUG("Pushing %s from GValue\n", g_type_tag_to_string(tag)); switch (tag) { /* basic types */ case GI_TYPE_TAG_VOID:{ GITypeInfo * cellinfo = g_type_info_get_param_type(info, 0); if (cellinfo) { GITypeTag ctag = g_type_info_get_tag(cellinfo); GY_DEBUG("void contains %s\n", g_type_tag_to_string(ctag)); g_base_info_unref(cellinfo); } ypush_nil(); break;} case GI_TYPE_TAG_BOOLEAN: *ypush_c(NULL) = g_value_get_boolean(pval); break; case GI_TYPE_TAG_INT8: *ypush_gint8(NULL) = g_value_get_schar(pval); break; case GI_TYPE_TAG_UINT8: *ypush_guint8(NULL)= g_value_get_uchar(pval); break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_INT32: *ypush_gint32(NULL) = g_value_get_int(pval); break; case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_UINT32: *ypush_guint32(NULL) = g_value_get_uint(pval); break; case GI_TYPE_TAG_INT64: ypush_long(g_value_get_int64(pval)); break; case GI_TYPE_TAG_UINT64: ypush_long(g_value_get_uint64(pval)); break; case GI_TYPE_TAG_FLOAT: *ypush_f(NULL)=g_value_get_float(pval); break; case GI_TYPE_TAG_DOUBLE: ypush_double(g_value_get_double(pval)); break; case GI_TYPE_TAG_GTYPE: ypush_long(g_value_get_gtype(pval)); break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: *ypush_q(NULL) = p_strcpy(g_value_get_string(pval)); break; /* array types */ case GI_TYPE_TAG_ARRAY: y_error("array"); break; /* interface types */ case GI_TYPE_TAG_INTERFACE: { GIBaseInfo * itrf = g_type_info_get_interface (info); switch(g_base_info_get_type (itrf)) { case GI_INFO_TYPE_ENUM: ypush_long(g_value_get_enum(pval)); g_base_info_unref(itrf); break; case GI_INFO_TYPE_OBJECT: { GObject * prop=g_value_get_object(pval); g_object_ref_sink(prop); if (!prop) { g_base_info_unref(itrf); y_error("get property failed"); } GY_DEBUG("pushing result... "); ypush_check(1); gy_Object * out = ypush_gy_Object(); out->info=itrf; out->object=prop; out->repo=o->repo; } break; default: g_base_info_unref(itrf); y_error ("fix me: only properties of type object supported yet"); } break; } default: y_error("Unimplemented"); } }
void gy_value_init(GValue * val, GITypeInfo * info) { GY_DEBUG("in gy_value_init\n"); GITypeTag type = g_type_info_get_tag(info); GIBaseInfo * itrf; GY_DEBUG("Initializing GValue to %s\n", g_type_tag_to_string(type)); switch (type) { /* basic types */ case GI_TYPE_TAG_BOOLEAN: g_value_init(val, G_TYPE_BOOLEAN); break; case GI_TYPE_TAG_INT8: g_value_init(val, G_TYPE_CHAR); break; case GI_TYPE_TAG_UINT8: g_value_init(val, G_TYPE_UCHAR); break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_INT32: g_value_init(val, G_TYPE_INT); break; case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_UINT32: g_value_init(val, G_TYPE_INT); break; case GI_TYPE_TAG_INT64: g_value_init(val, G_TYPE_INT64); break; case GI_TYPE_TAG_UINT64: g_value_init(val, G_TYPE_UINT64); break; case GI_TYPE_TAG_FLOAT: g_value_init(val, G_TYPE_FLOAT); break; case GI_TYPE_TAG_DOUBLE: g_value_init(val, G_TYPE_DOUBLE); break; case GI_TYPE_TAG_GTYPE: g_value_init(val, G_TYPE_GTYPE); break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: g_value_init(val, G_TYPE_STRING); GY_DEBUG("GValue is string\n"); break; /* interface types */ case GI_TYPE_TAG_INTERFACE: itrf = g_type_info_get_interface(info); switch(g_base_info_get_type (itrf)) { case GI_INFO_TYPE_OBJECT: g_value_init(val, G_TYPE_OBJECT); break; case GI_INFO_TYPE_ENUM: g_value_init(val, g_registered_type_info_get_g_type(itrf)); GY_DEBUG("GValue is enum\n"); break; default: y_errorn("Unimplemented GValue interface type %ld", g_base_info_get_type (itrf)); } g_base_info_unref(itrf); break; case GI_TYPE_TAG_VOID: default: y_error("Unimplement property GValue type"); } GY_DEBUG("out gy_value_init\n"); }
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; }
gint pygi_set_property_value_real (PyGObject *instance, const gchar *attr_name, PyObject *py_value) { GType g_type; GIPropertyInfo *property_info = NULL; char *property_name = g_strdup (attr_name); GITypeInfo *type_info = NULL; GITypeTag type_tag; GITransfer transfer; GValue value = { 0, }; GIArgument arg = { 0, }; GParamSpec *pspec = NULL; gint ret_value = -1; 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; if (! (pspec->flags & G_PARAM_WRITABLE)) goto out; type_info = g_property_info_get_type (property_info); transfer = g_property_info_get_ownership_transfer (property_info); arg = _pygi_argument_from_object (py_value, type_info, transfer); if (PyErr_Occurred()) goto out; g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); // FIXME: Lots of types still unhandled type_tag = g_type_info_get_tag (type_info); switch (type_tag) { 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: g_value_set_enum (&value, arg.v_int32); break; case GI_INFO_TYPE_INTERFACE: case GI_INFO_TYPE_OBJECT: g_value_set_object (&value, arg.v_pointer); 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)) { g_value_set_boxed (&value, arg.v_pointer); } else { PyErr_Format (PyExc_NotImplementedError, "Setting properties of type '%s' is not implemented", g_type_name (type)); } break; default: PyErr_Format (PyExc_NotImplementedError, "Setting properties of type '%s' is not implemented", g_type_name (type)); goto out; } break; } case GI_TYPE_TAG_BOOLEAN: g_value_set_boolean (&value, arg.v_boolean); break; case GI_TYPE_TAG_INT8: g_value_set_schar (&value, arg.v_int8); break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_INT32: if (G_VALUE_HOLDS_LONG (&value)) g_value_set_long (&value, arg.v_long); else g_value_set_int (&value, arg.v_int); break; case GI_TYPE_TAG_INT64: if (G_VALUE_HOLDS_LONG (&value)) g_value_set_long (&value, arg.v_long); else g_value_set_int64 (&value, arg.v_int64); break; case GI_TYPE_TAG_UINT8: g_value_set_uchar (&value, arg.v_uint8); break; case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_UINT32: if (G_VALUE_HOLDS_ULONG (&value)) g_value_set_ulong (&value, arg.v_ulong); else g_value_set_uint (&value, arg.v_uint); break; case GI_TYPE_TAG_UINT64: if (G_VALUE_HOLDS_ULONG (&value)) g_value_set_ulong (&value, arg.v_ulong); else g_value_set_uint64 (&value, arg.v_uint64); break; case GI_TYPE_TAG_FLOAT: g_value_set_float (&value, arg.v_float); break; case GI_TYPE_TAG_DOUBLE: g_value_set_double (&value, arg.v_double); break; case GI_TYPE_TAG_GTYPE: g_value_set_gtype (&value, arg.v_size); break; case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: g_value_set_string (&value, arg.v_string); break; case GI_TYPE_TAG_GHASH: g_value_set_boxed (&value, arg.v_pointer); break; case GI_TYPE_TAG_GLIST: g_value_set_pointer (&value, arg.v_pointer); break; case GI_TYPE_TAG_ARRAY: { GArray *arg_items = (GArray*) arg.v_pointer; gchar** strings; int i; if (arg_items == NULL) goto out; strings = g_new0 (char*, arg_items->len); for (i = 0; i < arg_items->len; ++i) { strings[i] = g_array_index (arg_items, GIArgument, i).v_string; } g_array_free (arg_items, TRUE); g_value_set_boxed (&value, strings); break; } default: PyErr_Format (PyExc_NotImplementedError, "Setting properties of type %s is not implemented", g_type_tag_to_string (g_type_info_get_tag (type_info))); goto out; } g_object_set_property (instance->obj, attr_name, &value); ret_value = 0; 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 ret_value; }
/** * 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; }
/** * 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; }
GIArgument * rb_gi_in_argument_from_ruby(GIArgument *argument, GITypeInfo *type_info, VALUE rb_argument) { GITypeTag type_tag; memset(argument, 0, sizeof(GIArgument)); type_tag = g_type_info_get_tag(type_info); switch (type_tag) { case GI_TYPE_TAG_VOID: break; case GI_TYPE_TAG_BOOLEAN: argument->v_boolean = RVAL2CBOOL(rb_argument); break; case GI_TYPE_TAG_INT8: argument->v_int8 = NUM2INT(rb_argument); break; case GI_TYPE_TAG_UINT8: argument->v_uint8 = NUM2UINT(rb_argument); break; case GI_TYPE_TAG_INT16: argument->v_int16 = NUM2INT(rb_argument); break; case GI_TYPE_TAG_UINT16: argument->v_uint16 = NUM2UINT(rb_argument); break; case GI_TYPE_TAG_INT32: argument->v_int32 = NUM2INT(rb_argument); break; case GI_TYPE_TAG_UINT32: argument->v_uint32 = NUM2UINT(rb_argument); break; case GI_TYPE_TAG_INT64: argument->v_int64 = NUM2LONG(rb_argument); break; case GI_TYPE_TAG_UINT64: argument->v_uint64 = NUM2ULONG(rb_argument); break; case GI_TYPE_TAG_FLOAT: argument->v_float = NUM2DBL(rb_argument); break; case GI_TYPE_TAG_DOUBLE: argument->v_double = NUM2DBL(rb_argument); break; case GI_TYPE_TAG_GTYPE: /* TODO: support GLib::Type and String as GType name. */ argument->v_size = NUM2ULONG(rb_argument); break; case GI_TYPE_TAG_UTF8: /* TODO: support UTF-8 convert like rb_argument.encode("UTF-8"). */ argument->v_string = (gchar *)RVAL2CSTR(rb_argument); break; case GI_TYPE_TAG_FILENAME: argument->v_string = (gchar *)RVAL2CSTR(rb_argument); break; case GI_TYPE_TAG_ARRAY: rb_gi_argument_from_ruby_array(argument, type_info, rb_argument); break; case GI_TYPE_TAG_INTERFACE: rb_gi_argument_from_ruby_interface(argument, type_info, rb_argument); break; case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_ERROR: case GI_TYPE_TAG_UNICHAR: rb_raise(rb_eNotImpError, "TODO: Ruby -> GIArgument(%s)", g_type_tag_to_string(type_tag)); break; default: g_assert_not_reached(); break; } return argument; }
static SV * ghash_to_sv (GITypeInfo *info, gpointer pointer, GITransfer transfer) { GITypeInfo *key_param_info, *value_param_info; #ifdef NOISY GITypeTag key_type_tag, value_type_tag; #endif gpointer key_p, value_p; GITransfer item_transfer; GHashTableIter iter; HV *hv; if (pointer == NULL) { return &PL_sv_undef; } item_transfer = transfer == GI_TRANSFER_EVERYTHING ? GI_TRANSFER_EVERYTHING : GI_TRANSFER_NOTHING; key_param_info = g_type_info_get_param_type (info, 0); value_param_info = g_type_info_get_param_type (info, 1); #ifdef NOISY key_type_tag = g_type_info_get_tag (key_param_info); value_type_tag = g_type_info_get_tag (value_param_info); #endif dwarn (" GHashTable: pointer %p\n" " key type tag %d (%s)\n" " value type tag %d (%s)\n", pointer, key_type_tag, g_type_tag_to_string (key_type_tag), value_type_tag, g_type_tag_to_string (value_type_tag)); hv = newHV (); g_hash_table_iter_init (&iter, pointer); while (g_hash_table_iter_next (&iter, &key_p, &value_p)) { GIArgument arg = { 0, }; SV *key_sv, *value_sv; dwarn (" converting key pointer %p\n", key_p); arg.v_pointer = key_p; key_sv = arg_to_sv (&arg, key_param_info, item_transfer, NULL); if (key_sv == NULL) break; dwarn (" converting value pointer %p\n", value_p); arg.v_pointer = value_p; value_sv = arg_to_sv (&arg, value_param_info, item_transfer, NULL); if (value_sv == NULL) break; (void) hv_store_ent (hv, key_sv, value_sv, 0); } g_base_info_unref ((GIBaseInfo *) key_param_info); g_base_info_unref ((GIBaseInfo *) value_param_info); return newRV_noinc ((SV *) hv); }
static gpointer sv_to_ghash (GITransfer transfer, GITypeInfo *type_info, SV *sv) { HV *hv; HE *he; GITransfer item_transfer; gpointer hash; GITypeInfo *key_param_info, *value_param_info; GITypeTag key_type_tag; GHashFunc hash_func; GEqualFunc equal_func; I32 n_keys; dwarn ("%s: sv %p\n", G_STRFUNC, sv); if (!gperl_sv_is_defined (sv)) return NULL; if (!gperl_sv_is_hash_ref (sv)) ccroak ("need an hash ref to convert to GHashTable"); hv = (HV *) SvRV (sv); item_transfer = GI_TRANSFER_NOTHING; switch (transfer) { case GI_TRANSFER_EVERYTHING: item_transfer = GI_TRANSFER_EVERYTHING; break; case GI_TRANSFER_CONTAINER: /* nothing special to do */ break; case GI_TRANSFER_NOTHING: /* FIXME: need to free hash after call */ break; } key_param_info = g_type_info_get_param_type (type_info, 0); value_param_info = g_type_info_get_param_type (type_info, 1); key_type_tag = g_type_info_get_tag (key_param_info); switch (key_type_tag) { case GI_TYPE_TAG_FILENAME: case GI_TYPE_TAG_UTF8: hash_func = g_str_hash; equal_func = g_str_equal; break; default: hash_func = NULL; equal_func = NULL; break; } dwarn (" GHashTable with transfer %d\n" " key_param_info %p with type tag %d (%s)\n" " value_param_info %p with type tag %d (%s)\n", transfer, key_param_info, g_type_info_get_tag (key_param_info), g_type_tag_to_string (g_type_info_get_tag (key_param_info)), value_param_info, g_type_info_get_tag (value_param_info), g_type_tag_to_string (g_type_info_get_tag (value_param_info))); hash = g_hash_table_new (hash_func, equal_func); n_keys = hv_iterinit (hv); if (n_keys == 0) goto out; while ((he = hv_iternext (hv)) != NULL) { SV *sv; GIArgument arg = { 0, }; gpointer key_p, value_p; key_p = value_p = NULL; sv = hv_iterkeysv (he); if (sv && gperl_sv_is_defined (sv)) { dwarn (" converting key SV %p\n", sv); /* FIXME: Is it OK to always allow undef here? */ sv_to_arg (sv, &arg, NULL, key_param_info, item_transfer, TRUE, NULL); key_p = arg.v_pointer; } sv = hv_iterval (hv, he); if (sv && gperl_sv_is_defined (sv)) { dwarn (" converting value SV %p\n", sv); sv_to_arg (sv, &arg, NULL, key_param_info, item_transfer, TRUE, NULL); value_p = arg.v_pointer; } if (key_p != NULL && value_p != NULL) g_hash_table_insert (hash, key_p, value_p); } out: dwarn (" -> hash %p of size %d\n", hash, g_hash_table_size (hash)); g_base_info_unref ((GIBaseInfo *) key_param_info); g_base_info_unref ((GIBaseInfo *) value_param_info); return hash; }
static gboolean get_type_size_alignment (GIrTypelibBuild *build, GIrNodeType *type, gint *size, gint *alignment, const char *who) { ffi_type *type_ffi; if (type->is_pointer) { type_ffi = &ffi_type_pointer; } else if (type->tag == GI_TYPE_TAG_ARRAY) { gint elt_size, elt_alignment; if (!type->has_size || !get_type_size_alignment(build, type->parameter_type1, &elt_size, &elt_alignment, who)) { *size = -1; *alignment = -1; return FALSE; } *size = type->size * elt_size; *alignment = elt_alignment; return TRUE; } else { if (type->tag == GI_TYPE_TAG_INTERFACE) { return get_interface_size_alignment (build, type, size, alignment, who); } else { type_ffi = gi_type_tag_get_ffi_type (type->tag, type->is_pointer); if (type_ffi == &ffi_type_void) { g_warning ("%s has void type", who); *size = -1; *alignment = -1; return FALSE; } else if (type_ffi == &ffi_type_pointer) { g_warning ("%s has is not a pointer and is of type %s", who, g_type_tag_to_string (type->tag)); *size = -1; *alignment = -1; return FALSE; } } } g_assert (type_ffi); *size = type_ffi->size; *alignment = type_ffi->alignment; return TRUE; }
static void invoke_callback (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata) { GPerlI11nPerlCallbackInfo *info; GICallableInfo *cb_interface; GPerlI11nInvocationInfo iinfo = {0,}; guint i; guint in_inout; guint n_return_values, n_returned; I32 context; dGPERL_CALLBACK_MARSHAL_SP; PERL_UNUSED_VAR (cif); /* unwrap callback info struct from userdata */ info = (GPerlI11nPerlCallbackInfo *) userdata; cb_interface = (GICallableInfo *) info->interface; prepare_perl_invocation_info (&iinfo, cb_interface); /* set perl context */ GPERL_CALLBACK_MARSHAL_INIT (info); ENTER; SAVETMPS; PUSHMARK (SP); /* find arguments; use type information from interface to find in and * in-out args and their types, count in-out and out args, and find * suitable converters; push in and in-out arguments onto the perl * stack */ in_inout = 0; for (i = 0; i < iinfo.n_args; i++) { GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i); GITypeInfo *arg_type = g_arg_info_get_type (arg_info); GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info); GIDirection direction = g_arg_info_get_direction (arg_info); iinfo.current_pos = i; /* the closure argument, which we handle separately, is marked * by having get_closure == i */ if (g_arg_info_get_closure (arg_info) == (gint) i) { g_base_info_unref ((GIBaseInfo *) arg_info); g_base_info_unref ((GIBaseInfo *) arg_type); continue; } dwarn ("arg info: %s (%p)\n" " direction: %d\n" " is return value: %d\n" " is optional: %d\n" " may be null: %d\n" " transfer: %d\n", g_base_info_get_name (arg_info), arg_info, g_arg_info_get_direction (arg_info), g_arg_info_is_return_value (arg_info), g_arg_info_is_optional (arg_info), g_arg_info_may_be_null (arg_info), g_arg_info_get_ownership_transfer (arg_info)); dwarn ("arg type: %p\n" " is pointer: %d\n" " tag: %s (%d)\n", arg_type, g_type_info_is_pointer (arg_type), g_type_tag_to_string (g_type_info_get_tag (arg_type)), g_type_info_get_tag (arg_type)); if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) { GIArgument arg; SV *sv; raw_to_arg (args[i], &arg, arg_type); sv = arg_to_sv (&arg, arg_type, transfer, &iinfo); /* If arg_to_sv returns NULL, we take that as 'skip * this argument'; happens for GDestroyNotify, for * example. */ if (sv) XPUSHs (sv_2mortal (sv)); } if (direction == GI_DIRECTION_INOUT || direction == GI_DIRECTION_OUT) { in_inout++; } g_base_info_unref ((GIBaseInfo *) arg_info); g_base_info_unref ((GIBaseInfo *) arg_type); } /* push user data onto the Perl stack */ if (info->data) XPUSHs (sv_2mortal (SvREFCNT_inc (info->data))); PUTBACK; /* determine suitable Perl call context */ context = G_VOID | G_DISCARD; if (iinfo.has_return_value) { context = in_inout > 0 ? G_ARRAY : G_SCALAR; } else { if (in_inout == 1) { context = G_SCALAR; } else if (in_inout > 1) { context = G_ARRAY; } } /* do the call, demand #in-out+#out+#return-value return values */ n_return_values = iinfo.has_return_value ? in_inout + 1 : in_inout; n_returned = info->sub_name ? call_method (info->sub_name, context) : call_sv (info->code, context); if (n_return_values != 0 && n_returned != n_return_values) { ccroak ("callback returned %d values " "but is supposed to return %d values", n_returned, n_return_values); } /* call-scoped callback infos are freed by * Glib::Object::Introspection::_FuncWrapper::DESTROY */ SPAGAIN; /* convert in-out and out values and stuff them back into args */ if (in_inout > 0) { SV **returned_values; int out_index; returned_values = g_new0 (SV *, in_inout); /* pop scalars off the stack and put them into the array; * reverse the order since POPs pops items off of the end of * the stack. */ for (i = 0; i < in_inout; i++) { returned_values[in_inout - i - 1] = POPs; } out_index = 0; for (i = 0; i < iinfo.n_args; i++) { GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i); GITypeInfo *arg_type = g_arg_info_get_type (arg_info); GIDirection direction = g_arg_info_get_direction (arg_info); gpointer out_pointer = * (gpointer *) args[i]; if (!out_pointer) { dwarn ("skipping out arg %d\n", i); g_base_info_unref (arg_info); g_base_info_unref (arg_type); continue; } if (direction == GI_DIRECTION_INOUT || direction == GI_DIRECTION_OUT) { GIArgument tmp_arg; GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info); gboolean may_be_null = g_arg_info_may_be_null (arg_info); gboolean is_caller_allocated = g_arg_info_is_caller_allocates (arg_info); if (is_caller_allocated) { tmp_arg.v_pointer = out_pointer; } sv_to_arg (returned_values[out_index], &tmp_arg, arg_info, arg_type, transfer, may_be_null, &iinfo); if (!is_caller_allocated) { arg_to_raw (&tmp_arg, out_pointer, arg_type); } out_index++; } g_base_info_unref (arg_info); g_base_info_unref (arg_type); } g_free (returned_values); }
static SV * arg_to_sv (GIArgument * arg, GITypeInfo * info, GITransfer transfer, GPerlI11nInvocationInfo *iinfo) { GITypeTag tag = g_type_info_get_tag (info); gboolean own = transfer >= GI_TRANSFER_CONTAINER; dwarn (" arg_to_sv: info %p with type tag %d (%s)\n", info, tag, g_type_tag_to_string (tag)); switch (tag) { case GI_TYPE_TAG_VOID: { SV *sv = callback_data_to_sv (arg->v_pointer, iinfo); dwarn (" argument with no type information -> %s\n", sv ? "callback data" : "undef"); return sv ? SvREFCNT_inc (sv) : &PL_sv_undef; } case GI_TYPE_TAG_BOOLEAN: return boolSV (arg->v_boolean); case GI_TYPE_TAG_INT8: return newSViv (arg->v_int8); case GI_TYPE_TAG_UINT8: return newSVuv (arg->v_uint8); case GI_TYPE_TAG_INT16: return newSViv (arg->v_int16); case GI_TYPE_TAG_UINT16: return newSVuv (arg->v_uint16); case GI_TYPE_TAG_INT32: return newSViv (arg->v_int32); case GI_TYPE_TAG_UINT32: return newSVuv (arg->v_uint32); case GI_TYPE_TAG_INT64: return newSVGInt64 (arg->v_int64); case GI_TYPE_TAG_UINT64: return newSVGUInt64 (arg->v_uint64); case GI_TYPE_TAG_FLOAT: return newSVnv (arg->v_float); case GI_TYPE_TAG_DOUBLE: return newSVnv (arg->v_double); case GI_TYPE_TAG_UNICHAR: { SV *sv; gchar buffer[6]; gint length = g_unichar_to_utf8 (arg->v_uint32, buffer); sv = newSVpv (buffer, length); SvUTF8_on (sv); return sv; } case GI_TYPE_TAG_GTYPE: { /* GType == gsize */ const char *package = gperl_package_from_type (arg->v_size); if (!package) package = g_type_name (arg->v_size); return newSVpv (package, PL_na); } case GI_TYPE_TAG_ARRAY: return array_to_sv (info, arg->v_pointer, transfer, iinfo); case GI_TYPE_TAG_INTERFACE: return interface_to_sv (info, arg, own, iinfo); case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: return glist_to_sv (info, arg->v_pointer, transfer); case GI_TYPE_TAG_GHASH: return ghash_to_sv (info, arg->v_pointer, transfer); case GI_TYPE_TAG_ERROR: ccroak ("FIXME - GI_TYPE_TAG_ERROR"); break; case GI_TYPE_TAG_UTF8: { SV *sv = newSVGChar (arg->v_string); if (own) g_free (arg->v_string); return sv; } case GI_TYPE_TAG_FILENAME: { SV *sv = newSVpv (arg->v_string, PL_na); if (own) g_free (arg->v_string); return sv; } default: ccroak ("Unhandled info tag %d in arg_to_sv", tag); } return NULL; }
VALUE rb_gi_argument_to_ruby(GIArgument *argument, GITypeInfo *type_info) { VALUE rb_argument = Qnil; GITypeTag type_tag; type_tag = g_type_info_get_tag(type_info); switch (type_tag) { case GI_TYPE_TAG_VOID: rb_argument = Qnil; break; case GI_TYPE_TAG_BOOLEAN: rb_argument = CBOOL2RVAL(argument->v_boolean); break; case GI_TYPE_TAG_INT8: rb_argument = INT2NUM(argument->v_int8); break; case GI_TYPE_TAG_UINT8: rb_argument = UINT2NUM(argument->v_uint8); break; case GI_TYPE_TAG_INT16: rb_argument = INT2NUM(argument->v_int16); break; case GI_TYPE_TAG_UINT16: rb_argument = UINT2NUM(argument->v_uint16); break; case GI_TYPE_TAG_INT32: rb_argument = INT2NUM(argument->v_int32); break; case GI_TYPE_TAG_UINT32: rb_argument = UINT2NUM(argument->v_uint32); break; case GI_TYPE_TAG_INT64: rb_argument = LONG2NUM(argument->v_int64); break; case GI_TYPE_TAG_UINT64: rb_argument = ULONG2NUM(argument->v_uint64); break; case GI_TYPE_TAG_FLOAT: rb_argument = DBL2NUM(argument->v_float); break; case GI_TYPE_TAG_DOUBLE: rb_argument = DBL2NUM(argument->v_double); break; case GI_TYPE_TAG_GTYPE: rb_argument = rbgobj_gtype_new(argument->v_size); break; case GI_TYPE_TAG_UTF8: rb_argument = CSTR2RVAL(argument->v_string); break; case GI_TYPE_TAG_FILENAME: /* TODO: set encoding */ rb_argument = CSTR2RVAL(argument->v_string); break; case GI_TYPE_TAG_ARRAY: rb_argument = array_to_ruby(argument->v_pointer, type_info); break; case GI_TYPE_TAG_INTERFACE: rb_argument = interface_to_ruby(argument, type_info); break; case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: case GI_TYPE_TAG_GHASH: rb_raise(rb_eNotImpError, "TODO: GIArgument(unichar) -> Ruby"); break; case GI_TYPE_TAG_ERROR: rb_argument = GERROR2RVAL(argument->v_pointer); break; case GI_TYPE_TAG_UNICHAR: rb_raise(rb_eNotImpError, "TODO: GIArgument(%s) -> Ruby", g_type_tag_to_string(type_tag)); break; default: g_assert_not_reached(); break; } return rb_argument; }