From: Kouhei S. <nu...@co...> - 2017-07-10 14:28:59
|
Kouhei Sutou 2017-07-10 23:27:28 +0900 (Mon, 10 Jul 2017) New Revision: 6a4c1bed52952668136324446da8d35b241f7097 https://github.com/ruby-gnome2/ruby-gnome2/commit/6a4c1bed52952668136324446da8d35b241f7097 Message: gi: support not pointer struct field reader GitHub: fix #1042 Reported by cedlemo. Thanks!!! Modified files: gobject-introspection/ext/gobject-introspection/rb-gi-argument.c gobject-introspection/ext/gobject-introspection/rb-gi-field-info.c gobject-introspection/ext/gobject-introspection/rb-gi-interface-info.c gobject-introspection/ext/gobject-introspection/rb-gi-private.h gobject-introspection/ext/gobject-introspection/rb-gi-struct-info.c gobject-introspection/ext/gobject-introspection/rb-gobject-introspection.h Modified: gobject-introspection/ext/gobject-introspection/rb-gi-argument.c (+32 -100) =================================================================== --- gobject-introspection/ext/gobject-introspection/rb-gi-argument.c 2017-07-10 21:41:55 +0900 (2098e6c) +++ gobject-introspection/ext/gobject-introspection/rb-gi-argument.c 2017-07-10 23:27:28 +0900 (afd09c0) @@ -22,59 +22,6 @@ static VALUE rb_cGLibValue = Qnil; -static VALUE -interface_struct_to_ruby(gpointer object, - gboolean duplicate, - G_GNUC_UNUSED GITypeInfo *type_info, - GIBaseInfo *interface_info) -{ - const char *namespace; - const char *name; - VALUE rb_module; - VALUE rb_class; - gpointer target_object = object; - RUBY_DATA_FUNC free_func = NULL; - - namespace = g_base_info_get_namespace(interface_info); - name = g_base_info_get_name(interface_info); - - if (strcmp(namespace, "cairo") == 0) { - gchar *gtype_name; - GType gtype; - - gtype_name = g_strdup_printf("Cairo%s", name); - gtype = g_type_from_name(gtype_name); - g_free(gtype_name); - return BOXED2RVAL(target_object, gtype); - } - - rb_module = rb_const_get(rb_cObject, rb_intern(namespace)); - rb_class = rb_const_get(rb_module, rb_intern(name)); - if (rb_respond_to(rb_class, rb_intern("gtype"))) { - VALUE rb_gtype; - GType gtype; - - rb_gtype = rb_funcall(rb_class, rb_intern("gtype"), 0); - gtype = NUM2ULONG(rb_funcall(rb_gtype, rb_intern("to_i"), 0)); - return BOXED2RVAL(target_object, gtype); - } - - if (duplicate) { - size_t object_size; - object_size = g_struct_info_get_size(interface_info); - target_object = xmalloc(object_size); - memcpy(target_object, object, object_size); - free_func = xfree; - } - return Data_Wrap_Struct(rb_class, NULL, free_func, target_object); -} - -static gpointer -interface_struct_from_ruby(VALUE rb_object) -{ - return DATA_PTR(rb_object); -} - static void array_c_to_ruby_sized_interface(gconstpointer *elements, gint64 n_elements, @@ -107,10 +54,9 @@ array_c_to_ruby_sized_interface(gconstpointer *elements, if (gtype == G_TYPE_NONE) { for (i = 0; i < n_elements; i++) { rb_ary_push(rb_array, - interface_struct_to_ruby((gpointer)elements[i], - FALSE, - element_type_info, - interface_info)); + rb_gi_struct_info_to_ruby(interface_info, + (gpointer)elements[i], + TRUE)); } g_base_info_unref(interface_info); g_base_info_unref(element_type_info); @@ -399,10 +345,9 @@ array_array_interface_to_ruby(GIArgument *array, gpointer element; element = elements->data + (element_size * i); rb_ary_push(rb_array, - interface_struct_to_ruby(element, - TRUE, - element_type_info, - interface_info)); + rb_gi_struct_info_to_ruby(interface_info, + element, + FALSE)); } } else { interface_name = g_info_type_to_string(interface_type); @@ -644,17 +589,9 @@ rb_gi_argument_to_ruby_interface(GIArgument *argument, "TODO: GIArgument(interface)[callback] -> Ruby"); break; case GI_INFO_TYPE_STRUCT: - if (gtype == G_TYPE_NONE) { - rb_interface = interface_struct_to_ruby(argument->v_pointer, - duplicate, - type_info, - interface_info); - } else if (gtype == G_TYPE_VARIANT) { - GVariant *variant = argument->v_pointer; - rb_interface = rbg_variant_to_ruby(variant); - } else { - rb_interface = BOXED2RVAL(argument->v_pointer, gtype); - } + rb_interface = rb_gi_struct_info_to_ruby(interface_info, + argument->v_pointer, + !duplicate); break; case GI_INFO_TYPE_BOXED: rb_raise(rb_eNotImpError, @@ -879,10 +816,9 @@ rb_gi_argument_to_ruby_glist_interface(GIArgument *argument, rb_argument = rb_ary_new(); for (node = argument->v_pointer; node; node = g_list_next(node)) { rb_ary_push(rb_argument, - interface_struct_to_ruby(node->data, - FALSE, - element_type_info, - interface_info)); + rb_gi_struct_info_to_ruby(interface_info, + node->data, + TRUE)); } } else { rb_argument = BOXEDGLIST2RVAL(argument->v_pointer, gtype); @@ -1030,10 +966,9 @@ rb_gi_argument_to_ruby_gslist_interface(GIArgument *argument, rb_argument = rb_ary_new(); for (node = argument->v_pointer; node; node = g_slist_next(node)) { rb_ary_push(rb_argument, - interface_struct_to_ruby(node->data, - FALSE, - element_type_info, - interface_info)); + rb_gi_struct_info_to_ruby(interface_info, + node->data, + TRUE)); } } else { rb_argument = BOXEDGLIST2RVAL(argument->v_pointer, gtype); @@ -3479,7 +3414,7 @@ set_in_array_gtype_arguments_from_ruby(GIArgument *array_argument, typedef struct { GType element_gtype; - gsize element_size; + GIStructInfo *struct_info; VALUE rb_argument; gint n_args; gchar *values; @@ -3489,23 +3424,22 @@ static VALUE set_in_array_interface_struct_arguments_from_ruby_body(VALUE value) { ArrayInterfaceStructFromRubyData *data; + gsize size; gint i; data = (ArrayInterfaceStructFromRubyData *)value; + size = g_struct_info_get_size(data->struct_info); + data->values = xmalloc(size * data->n_args); for (i = 0; i < data->n_args; i++) { VALUE rb_element; gpointer element; rb_element = RARRAY_PTR(data->rb_argument)[i]; - if (data->element_gtype == G_TYPE_NONE) { - element = interface_struct_from_ruby(rb_element); - } else { - element = RVAL2BOXED(rb_element, data->element_gtype); - } - memcpy(data->values + (data->element_size * i), + element = rb_gi_struct_info_from_ruby(data->struct_info, rb_element); + memcpy(data->values + (size * i), element, - data->element_size); + size); } return Qnil; @@ -3517,6 +3451,7 @@ set_in_array_interface_struct_arguments_from_ruby_rescue(VALUE value) ArrayInterfaceStructFromRubyData *data; data = (ArrayInterfaceStructFromRubyData *)value; + g_base_info_unref((GIBaseInfo *)(data->struct_info)); xfree(data->values); rb_exc_raise(rb_errinfo()); @@ -3524,17 +3459,15 @@ set_in_array_interface_struct_arguments_from_ruby_rescue(VALUE value) static void set_in_array_interface_struct_arguments_from_ruby(GIArgument *array_argument, - GType element_gtype, - gsize element_size, + GIStructInfo *struct_info, VALUE rb_argument) { ArrayInterfaceStructFromRubyData data; - data.element_gtype = element_gtype; - data.element_size = element_size; + data.struct_info = struct_info; data.rb_argument = rb_argument; data.n_args = RARRAY_LEN(rb_argument); - data.values = xmalloc(data.element_size * data.n_args); + data.values = NULL; rb_rescue(set_in_array_interface_struct_arguments_from_ruby_body, (VALUE)&data, set_in_array_interface_struct_arguments_from_ruby_rescue, @@ -3551,7 +3484,6 @@ set_in_array_interface_arguments_from_ruby(GIArgument *array_argument, GIInfoType interface_type; GType gtype; const char *interface_name; - gsize size; interface_info = g_type_info_get_interface(element_type_info); interface_type = g_base_info_get_type(interface_info); @@ -3569,12 +3501,12 @@ set_in_array_interface_arguments_from_ruby(GIArgument *array_argument, g_type_name(gtype)); break; case GI_INFO_TYPE_STRUCT: - size = g_struct_info_get_size(interface_info); - g_base_info_unref(interface_info); - set_in_array_interface_struct_arguments_from_ruby(array_argument, - gtype, - size, - rb_argument); + { + GIStructInfo *struct_info = (GIStructInfo *)interface_info; + set_in_array_interface_struct_arguments_from_ruby(array_argument, + struct_info, + rb_argument); + } break; case GI_INFO_TYPE_BOXED: case GI_INFO_TYPE_ENUM: Modified: gobject-introspection/ext/gobject-introspection/rb-gi-field-info.c (+146 -33) =================================================================== --- gobject-introspection/ext/gobject-introspection/rb-gi-field-info.c 2017-07-10 21:41:55 +0900 (58ebfc7) +++ gobject-introspection/ext/gobject-introspection/rb-gi-field-info.c 2017-07-10 23:27:28 +0900 (9179e4a) @@ -71,6 +71,69 @@ rg_type(VALUE self) return GI_BASE_INFO2RVAL_WITH_UNREF(g_field_info_get_type(info)); } +static VALUE +rb_gi_field_info_get_field_raw_interface(GIFieldInfo *info, + gpointer memory, + GITypeInfo *type_info) +{ + VALUE rb_field_value = Qnil; + GIBaseInfo *interface_info; + GIInfoType interface_type; + + interface_info = g_type_info_get_interface(type_info); + interface_type = g_base_info_get_type(interface_info); + switch (interface_type) { + case GI_INFO_TYPE_INVALID: + case GI_INFO_TYPE_FUNCTION: + case GI_INFO_TYPE_CALLBACK: + break; + case GI_INFO_TYPE_STRUCT: + { + GIStructInfo *struct_info = (GIStructInfo *)interface_info; + gint offset; + + offset = g_field_info_get_offset(info); + rb_field_value = rb_gi_struct_info_to_ruby( + struct_info, + (gchar *)memory + offset, + g_type_info_is_pointer(type_info)); + break; + } + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_UNION: + case GI_INFO_TYPE_OBJECT: + { + GIArgument argument; + gint offset; + + offset = g_field_info_get_offset(info); + argument.v_pointer = G_STRUCT_MEMBER(gpointer, memory, offset); + rb_field_value = GI_ARGUMENT2RVAL(&argument, FALSE, type_info, + NULL, NULL, NULL); + } + break; + case GI_INFO_TYPE_ENUM: + case GI_INFO_TYPE_FLAGS: + case GI_INFO_TYPE_INTERFACE: + case GI_INFO_TYPE_CONSTANT: + case GI_INFO_TYPE_INVALID_0: + case GI_INFO_TYPE_VALUE: + case GI_INFO_TYPE_SIGNAL: + case GI_INFO_TYPE_VFUNC: + 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: + break; + default: + break; + } + g_base_info_unref(interface_info); + + return rb_field_value; +} + VALUE rb_gi_field_info_get_field_raw(GIFieldInfo *info, gpointer memory) { @@ -78,36 +141,25 @@ rb_gi_field_info_get_field_raw(GIFieldInfo *info, gpointer memory) gboolean processed = FALSE; GITypeInfo *type_info; GITypeTag type_tag; - VALUE rb_field_value; + VALUE rb_field_value = Qnil; type_info = g_field_info_get_type(info); type_tag = g_type_info_get_tag(type_info); switch (type_tag) { - case GI_TYPE_TAG_INTERFACE: - { - GIBaseInfo *interface_info; - GIInfoType interface_type; - - interface_info = g_type_info_get_interface(type_info); - interface_type = g_base_info_get_type(interface_info); - switch (interface_type) { - case GI_INFO_TYPE_STRUCT: - case GI_INFO_TYPE_UNION: - case GI_INFO_TYPE_BOXED: - { - int offset; - - offset = g_field_info_get_offset(info); - argument.v_pointer = G_STRUCT_MEMBER(gpointer, memory, offset); - processed = TRUE; - } - break; - default: - break; - } - g_base_info_unref(interface_info); - } + case GI_TYPE_TAG_VOID: + 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_GTYPE: break; case GI_TYPE_TAG_UTF8: { @@ -117,6 +169,25 @@ rb_gi_field_info_get_field_raw(GIFieldInfo *info, gpointer memory) processed = TRUE; } break; + case GI_TYPE_TAG_FILENAME: + case GI_TYPE_TAG_ARRAY: + break; + case GI_TYPE_TAG_INTERFACE: + rb_field_value = + rb_gi_field_info_get_field_raw_interface(info, + memory, + type_info); + if (!NIL_P(rb_field_value)) { + g_base_info_unref(type_info); + return rb_field_value; + } + 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: + break; default: break; } @@ -153,6 +224,31 @@ rb_gi_field_info_set_field_raw(GIFieldInfo *info, gpointer memory, succeeded = g_field_info_set_field(info, memory, &field_value); if (!succeeded) { switch (type_tag) { + case GI_TYPE_TAG_VOID: + 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_GTYPE: + break; + case GI_TYPE_TAG_UTF8: + { + int offset; + offset = g_field_info_get_offset(info); + G_STRUCT_MEMBER(gchar *, memory, offset) = field_value.v_string; + succeeded = TRUE; + } + break; + case GI_TYPE_TAG_FILENAME: + case GI_TYPE_TAG_ARRAY: + break; case GI_TYPE_TAG_INTERFACE: { GIBaseInfo *interface_info; @@ -161,9 +257,13 @@ rb_gi_field_info_set_field_raw(GIFieldInfo *info, gpointer memory, interface_info = g_type_info_get_interface(type_info); interface_type = g_base_info_get_type(interface_info); switch (interface_type) { + case GI_INFO_TYPE_INVALID: + case GI_INFO_TYPE_FUNCTION: + case GI_INFO_TYPE_CALLBACK: + break; case GI_INFO_TYPE_STRUCT: - case GI_INFO_TYPE_UNION: case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_UNION: { int offset; @@ -173,19 +273,32 @@ rb_gi_field_info_set_field_raw(GIFieldInfo *info, gpointer memory, succeeded = TRUE; } break; + case GI_INFO_TYPE_ENUM: + case GI_INFO_TYPE_FLAGS: + case GI_INFO_TYPE_OBJECT: + case GI_INFO_TYPE_INTERFACE: + case GI_INFO_TYPE_CONSTANT: + case GI_INFO_TYPE_INVALID_0: + case GI_INFO_TYPE_VALUE: + case GI_INFO_TYPE_SIGNAL: + case GI_INFO_TYPE_VFUNC: + 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: + break; default: break; } g_base_info_unref(interface_info); } break; - case GI_TYPE_TAG_UTF8: - { - int offset; - offset = g_field_info_get_offset(info); - G_STRUCT_MEMBER(gchar *, memory, offset) = field_value.v_string; - succeeded = TRUE; - } + 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: break; default: break; Modified: gobject-introspection/ext/gobject-introspection/rb-gi-interface-info.c (+1 -1) =================================================================== --- gobject-introspection/ext/gobject-introspection/rb-gi-interface-info.c 2017-07-10 21:41:55 +0900 (e7304f7) +++ gobject-introspection/ext/gobject-introspection/rb-gi-interface-info.c 2017-07-10 23:27:28 +0900 (90d9122) @@ -1,6 +1,6 @@ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */ /* - * Copyright (C) 2012 Ruby-GNOME2 Project Team + * Copyright (C) 2012-2017 Ruby-GNOME2 Project Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public Modified: gobject-introspection/ext/gobject-introspection/rb-gi-private.h (+7 -1) =================================================================== --- gobject-introspection/ext/gobject-introspection/rb-gi-private.h 2017-07-10 21:41:55 +0900 (5f23319) +++ gobject-introspection/ext/gobject-introspection/rb-gi-private.h 2017-07-10 23:27:28 +0900 (4e48a53) @@ -1,6 +1,6 @@ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */ /* - * Copyright (C) 2012-2013 Ruby-GNOME2 Project Team + * Copyright (C) 2012-2017 Ruby-GNOME2 Project Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -105,4 +105,10 @@ void rb_gi_field_info_set_field_raw (GIFieldInfo *info, gpointer memory, VALUE rb_field_value); +VALUE rb_gi_struct_info_to_ruby(GIStructInfo *info, + gpointer object, + gboolean is_pointer); +gpointer rb_gi_struct_info_from_ruby(GIStructInfo *info, + VALUE rb_object); + #endif Modified: gobject-introspection/ext/gobject-introspection/rb-gi-struct-info.c (+71 -1) =================================================================== --- gobject-introspection/ext/gobject-introspection/rb-gi-struct-info.c 2017-07-10 21:41:55 +0900 (419e3c6) +++ gobject-introspection/ext/gobject-introspection/rb-gi-struct-info.c 2017-07-10 23:27:28 +0900 (7581053) @@ -28,13 +28,83 @@ gi_struct_info_get_type(void) { static GType type = 0; if (type == 0) { - type = g_boxed_type_register_static("GIStructInfo", + type = g_boxed_type_register_static("GIStructInfo", (GBoxedCopyFunc)g_base_info_ref, (GBoxedFreeFunc)g_base_info_unref); } return type; } +VALUE +rb_gi_struct_info_to_ruby(GIStructInfo *info, + gpointer object, + gboolean is_pointer) +{ + GIBaseInfo *base_info = (GIBaseInfo *)info; + GIRegisteredTypeInfo *registered_type_info = (GIRegisteredTypeInfo *)info; + GType gtype; + const char *namespace; + const char *name; + VALUE rb_module; + VALUE rb_class; + gpointer target_object = object; + RUBY_DATA_FUNC free_func = NULL; + + gtype = g_registered_type_info_get_g_type(registered_type_info); + if (gtype == G_TYPE_VARIANT) { + GVariant *variant = object; + return rbg_variant_to_ruby(variant); + } + + namespace = g_base_info_get_namespace(base_info); + name = g_base_info_get_name(base_info); + + if (strcmp(namespace, "cairo") == 0) { + gchar *gtype_name; + GType gtype; + + gtype_name = g_strdup_printf("Cairo%s", name); + gtype = g_type_from_name(gtype_name); + g_free(gtype_name); + return BOXED2RVAL(target_object, gtype); + } + + rb_module = rb_const_get(rb_cObject, rb_intern(namespace)); + rb_class = rb_const_get(rb_module, rb_intern(name)); + if (rb_respond_to(rb_class, rb_intern("gtype"))) { + VALUE rb_gtype; + GType gtype; + + rb_gtype = rb_funcall(rb_class, rb_intern("gtype"), 0); + gtype = NUM2ULONG(rb_funcall(rb_gtype, rb_intern("to_i"), 0)); + return BOXED2RVAL(target_object, gtype); + } + + if (!is_pointer) { + size_t object_size; + object_size = g_struct_info_get_size(info); + target_object = xmalloc(object_size); + memcpy(target_object, object, object_size); + free_func = xfree; + } + + return Data_Wrap_Struct(rb_class, NULL, free_func, target_object); +} + +gpointer +rb_gi_struct_info_from_ruby(GIStructInfo *info, VALUE rb_object) +{ + GIRegisteredTypeInfo *registerd_type_info = (GIRegisteredTypeInfo *)info; + GType gtype; + + gtype = g_registered_type_info_get_g_type(registerd_type_info); + if (gtype == G_TYPE_NONE) { + return DATA_PTR(rb_object); + } else { + return RVAL2BOXED(rb_object, gtype); + } +} + static VALUE rg_n_fields(VALUE self) { Modified: gobject-introspection/ext/gobject-introspection/rb-gobject-introspection.h (+1 -1) =================================================================== --- gobject-introspection/ext/gobject-introspection/rb-gobject-introspection.h 2017-07-10 21:41:55 +0900 (3b260b1) +++ gobject-introspection/ext/gobject-introspection/rb-gobject-introspection.h 2017-07-10 23:27:28 +0900 (4111264) @@ -1,6 +1,6 @@ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */ /* - * Copyright (C) 2012-2014 Ruby-GNOME2 Project Team + * Copyright (C) 2012-2017 Ruby-GNOME2 Project Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public |