gobject-introspection 3.4.4 → 3.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/gobject-introspection/rb-gi-argument.c +10 -3
- data/ext/gobject-introspection/rb-gi-arguments-in.c +26 -97
- data/ext/gobject-introspection/rb-gi-arguments.c +214 -7
- data/ext/gobject-introspection/rb-gi-base-info.c +11 -1
- data/ext/gobject-introspection/rb-gi-callable-info.c +10 -2
- data/ext/gobject-introspection/rb-gi-callback.c +156 -2
- data/ext/gobject-introspection/rb-gi-conversions.h +6 -6
- data/ext/gobject-introspection/rb-gi-loader.c +53 -1
- data/ext/gobject-introspection/rb-gi-object-info.c +11 -1
- data/ext/gobject-introspection/rb-gi-private-arguments-in.h +3 -1
- data/ext/gobject-introspection/rb-gi-private-arguments.h +5 -1
- data/ext/gobject-introspection/rb-gi-private-callback.h +6 -3
- data/ext/gobject-introspection/rb-gi-private.h +1 -0
- data/ext/gobject-introspection/rb-gi-struct-info.c +13 -1
- data/ext/gobject-introspection/rb-gi-vfunc-info.c +2 -2
- data/ext/gobject-introspection/rb-gobject-introspection.c +231 -0
- data/lib/gobject-introspection/loader.rb +65 -1
- data/test/run-test.rb +4 -0
- data/test/test-base-info.rb +5 -1
- data/test/test-callable-info.rb +7 -1
- data/test/test-loader.rb +53 -7
- data/test/test-object-info.rb +5 -1
- data/test/test-struct-info.rb +6 -1
- metadata +4 -4
@@ -1,6 +1,6 @@
|
|
1
1
|
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
2
|
/*
|
3
|
-
* Copyright (C) 2012-
|
3
|
+
* Copyright (C) 2012-2021 Ruby-GNOME Project Team
|
4
4
|
*
|
5
5
|
* This library is free software; you can redistribute it and/or
|
6
6
|
* modify it under the terms of the GNU Lesser General Public
|
@@ -194,6 +194,17 @@ rg_get_field(VALUE self, VALUE rb_n)
|
|
194
194
|
return GI_BASE_INFO2RVAL_WITH_UNREF(g_struct_info_get_field(info, n));
|
195
195
|
}
|
196
196
|
|
197
|
+
static VALUE
|
198
|
+
rg_find_field(VALUE self, VALUE rb_name)
|
199
|
+
{
|
200
|
+
GIStructInfo *info;
|
201
|
+
const gchar *name;
|
202
|
+
|
203
|
+
info = SELF(self);
|
204
|
+
name = RVAL2CSTR(rb_name);
|
205
|
+
return GI_BASE_INFO2RVAL_WITH_UNREF(g_struct_info_find_field(info, name));
|
206
|
+
}
|
207
|
+
|
197
208
|
static VALUE
|
198
209
|
rg_get_field_value(VALUE self, VALUE rb_struct, VALUE rb_n)
|
199
210
|
{
|
@@ -308,6 +319,7 @@ rb_gi_struct_info_init(VALUE rb_mGI, VALUE rb_cGIRegisteredTypeInfo)
|
|
308
319
|
|
309
320
|
RG_DEF_METHOD(n_fields, 0);
|
310
321
|
RG_DEF_METHOD(get_field, 1);
|
322
|
+
RG_DEF_METHOD(find_field, 1);
|
311
323
|
RG_DEF_METHOD(get_field_value, 2);
|
312
324
|
RG_DEF_METHOD(set_field_value, 3);
|
313
325
|
RG_DEF_METHOD(n_methods, 0);
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
2
|
/*
|
3
|
-
* Copyright (C) 2012 Ruby-
|
3
|
+
* Copyright (C) 2012-2021 Ruby-GNOME Project Team
|
4
4
|
*
|
5
5
|
* This library is free software; you can redistribute it and/or
|
6
6
|
* modify it under the terms of the GNU Lesser General Public
|
@@ -21,7 +21,7 @@
|
|
21
21
|
#include "rb-gi-private.h"
|
22
22
|
|
23
23
|
#define RG_TARGET_NAMESPACE rb_cGIVFuncInfo
|
24
|
-
#define SELF(self)
|
24
|
+
#define SELF(self) RVAL2GI_VFUNC_INFO(self)
|
25
25
|
|
26
26
|
GType
|
27
27
|
gi_vfunc_info_get_type(void)
|
@@ -22,6 +22,15 @@
|
|
22
22
|
|
23
23
|
#define RG_TARGET_NAMESPACE rb_mGObjectIntrospection
|
24
24
|
|
25
|
+
typedef struct {
|
26
|
+
ID name;
|
27
|
+
GICallableInfo *callable_info;
|
28
|
+
|
29
|
+
ffi_cif cif;
|
30
|
+
ffi_closure *closure;
|
31
|
+
} RBGIVFuncCallbackData;
|
32
|
+
|
33
|
+
static ID id_send;
|
25
34
|
static gboolean is_debug_mode = FALSE;
|
26
35
|
|
27
36
|
gboolean
|
@@ -30,11 +39,231 @@ rb_gi_is_debug_mode(void)
|
|
30
39
|
return is_debug_mode;
|
31
40
|
}
|
32
41
|
|
42
|
+
static void
|
43
|
+
find_vfunc_info (GIBaseInfo *vfunc_info,
|
44
|
+
GType implementor_gtype,
|
45
|
+
gpointer *implementor_vtable_ret,
|
46
|
+
GIFieldInfo **field_info_ret)
|
47
|
+
{
|
48
|
+
GIBaseInfo *ancestor_info = NULL;
|
49
|
+
GIStructInfo *struct_info = NULL;
|
50
|
+
GIFieldInfo *field_info = NULL;
|
51
|
+
|
52
|
+
ancestor_info = g_base_info_get_container(vfunc_info);
|
53
|
+
// ancestor_gtype = g_registered_type_info_get_g_type (
|
54
|
+
// (GIRegisteredTypeInfo *) ancestor_info);
|
55
|
+
struct_info = g_object_info_get_class_struct((GIObjectInfo*) ancestor_info);
|
56
|
+
*implementor_vtable_ret = g_type_class_ref(implementor_gtype);
|
57
|
+
|
58
|
+
field_info = g_struct_info_find_field(
|
59
|
+
struct_info, g_base_info_get_name((GIBaseInfo*) vfunc_info));
|
60
|
+
|
61
|
+
if (field_info != NULL) {
|
62
|
+
GITypeInfo *type_info;
|
63
|
+
|
64
|
+
type_info = g_field_info_get_type (field_info);
|
65
|
+
if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_INTERFACE) {
|
66
|
+
*field_info_ret = field_info;
|
67
|
+
} else {
|
68
|
+
g_base_info_unref (field_info);
|
69
|
+
}
|
70
|
+
g_base_info_unref (type_info);
|
71
|
+
}
|
72
|
+
|
73
|
+
g_base_info_unref (struct_info);
|
74
|
+
}
|
75
|
+
|
76
|
+
static VALUE
|
77
|
+
garg2rval(GIArgument *argument, GITypeTag type_tag)
|
78
|
+
{
|
79
|
+
switch (type_tag) {
|
80
|
+
case GI_TYPE_TAG_INT32:
|
81
|
+
return INT2FIX(argument->v_int32);
|
82
|
+
default:
|
83
|
+
rb_raise(rb_eTypeError, "garg2rval: not implemented");
|
84
|
+
break;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
static void
|
89
|
+
rval2garg(VALUE value, GITypeTag type_tag, GIArgument *argument)
|
90
|
+
{
|
91
|
+
switch (type_tag) {
|
92
|
+
case GI_TYPE_TAG_INT32:
|
93
|
+
argument->v_int32 = FIX2INT(value);
|
94
|
+
break;
|
95
|
+
default:
|
96
|
+
rb_raise(rb_eTypeError, "rval2garg: not implemented");
|
97
|
+
break;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
static void
|
102
|
+
rval2ffiarg(VALUE value, ffi_arg *arg)
|
103
|
+
{
|
104
|
+
switch (TYPE(value)) {
|
105
|
+
case T_NIL:
|
106
|
+
break;
|
107
|
+
case T_FIXNUM:
|
108
|
+
case T_DATA:
|
109
|
+
*arg = FIX2INT(value);
|
110
|
+
break;
|
111
|
+
default:
|
112
|
+
rb_raise(rb_eTypeError, "rval2ffiarg: not implemented");
|
113
|
+
break;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
static void
|
118
|
+
ffi_callback(G_GNUC_UNUSED ffi_cif *cif,
|
119
|
+
void *ret,
|
120
|
+
void **raw_args,
|
121
|
+
void *raw_data)
|
122
|
+
{
|
123
|
+
GIArgument **args = NULL;
|
124
|
+
RBGIVFuncCallbackData *data = NULL;
|
125
|
+
GObject* receiver = NULL;
|
126
|
+
VALUE rb_receiver = 0;
|
127
|
+
gint n_args = 0, n_in_args = 0, n_out_args = 0;
|
128
|
+
size_t i = 0, j = 0;
|
129
|
+
VALUE *in_values = NULL;
|
130
|
+
VALUE rb_ret;
|
131
|
+
GIArgInfo arg_info;
|
132
|
+
GITypeInfo type_info;
|
133
|
+
GITypeTag type_tag;
|
134
|
+
GIDirection direction;
|
135
|
+
gboolean ret_type_is_void;
|
136
|
+
|
137
|
+
args = (GIArgument **) raw_args;
|
138
|
+
data = (RBGIVFuncCallbackData *) raw_data;
|
139
|
+
|
140
|
+
receiver = G_OBJECT(args[0]->v_pointer);
|
141
|
+
rb_receiver = GOBJ2RVAL(receiver);
|
142
|
+
|
143
|
+
n_args = g_callable_info_get_n_args(data->callable_info);
|
144
|
+
in_values = (VALUE *) malloc(n_args * sizeof(VALUE));
|
145
|
+
in_values[0] = data->name;
|
146
|
+
n_in_args++;
|
147
|
+
|
148
|
+
for (i = 1, j = 1; i < n_args; i++) {
|
149
|
+
g_callable_info_load_arg(data->callable_info, i, &arg_info);
|
150
|
+
g_arg_info_load_type(&arg_info, &type_info);
|
151
|
+
type_tag = g_type_info_get_tag(&type_info);
|
152
|
+
direction = g_arg_info_get_direction(&arg_info);
|
153
|
+
|
154
|
+
if (type_tag == GI_TYPE_TAG_VOID) continue;
|
155
|
+
|
156
|
+
if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
|
157
|
+
n_out_args++;
|
158
|
+
|
159
|
+
if (direction == GI_DIRECTION_OUT) continue;
|
160
|
+
|
161
|
+
in_values[j] = garg2rval(args[i], type_tag);
|
162
|
+
j++; n_in_args++;
|
163
|
+
}
|
164
|
+
|
165
|
+
// result = rb_funcall(rb_receiver, id_send, 1, data->name);
|
166
|
+
rb_ret = rb_funcallv(rb_receiver, id_send, n_in_args, in_values);
|
167
|
+
|
168
|
+
g_callable_info_load_return_type(data->callable_info, &type_info);
|
169
|
+
ret_type_is_void = g_type_info_get_tag(&type_info) == GI_TYPE_TAG_VOID;
|
170
|
+
|
171
|
+
if (n_out_args == 0 && ret_type_is_void) {
|
172
|
+
// do nothing
|
173
|
+
} else if (n_out_args == 0) {
|
174
|
+
rval2ffiarg(rb_ret, ret);
|
175
|
+
} else if (n_out_args == 1 && ret_type_is_void) {
|
176
|
+
for (i = 1; i < n_args; i++) {
|
177
|
+
g_callable_info_load_arg(data->callable_info, i, &arg_info);
|
178
|
+
g_arg_info_load_type(&arg_info, &type_info);
|
179
|
+
type_tag = g_type_info_get_tag(&type_info);
|
180
|
+
direction = g_arg_info_get_direction(&arg_info);
|
181
|
+
|
182
|
+
if (type_tag == GI_TYPE_TAG_VOID || direction == GI_DIRECTION_IN)
|
183
|
+
continue;
|
184
|
+
|
185
|
+
rval2garg(rb_ret, type_tag, *(GIArgument **) args[i]);
|
186
|
+
break;
|
187
|
+
}
|
188
|
+
} else {
|
189
|
+
if (TYPE(rb_ret) != T_ARRAY) {
|
190
|
+
rb_raise(rb_eTypeError, "return type should be Array");
|
191
|
+
}
|
192
|
+
|
193
|
+
for (i = 1, j = 0; i < n_args; i++) {
|
194
|
+
g_callable_info_load_arg(data->callable_info, i, &arg_info);
|
195
|
+
g_arg_info_load_type(&arg_info, &type_info);
|
196
|
+
type_tag = g_type_info_get_tag(&type_info);
|
197
|
+
direction = g_arg_info_get_direction(&arg_info);
|
198
|
+
|
199
|
+
if (type_tag == GI_TYPE_TAG_VOID || direction == GI_DIRECTION_IN)
|
200
|
+
continue;
|
201
|
+
|
202
|
+
rval2garg(rb_ary_entry(rb_ret, j), type_tag, *(GIArgument **) args[i]);
|
203
|
+
j++;
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
free(in_values);
|
208
|
+
}
|
209
|
+
|
210
|
+
static VALUE
|
211
|
+
rb_gi_hook_up_vfunc(G_GNUC_UNUSED VALUE self,
|
212
|
+
VALUE rb_name,
|
213
|
+
VALUE rb_vfunc_info,
|
214
|
+
VALUE rb_gtype)
|
215
|
+
{
|
216
|
+
GIVFuncInfo *vfunc_info = NULL;
|
217
|
+
GType gtype = 0;
|
218
|
+
gpointer implementor_vtable = NULL;
|
219
|
+
GIFieldInfo *field_info = NULL;
|
220
|
+
|
221
|
+
vfunc_info = RVAL2GI_BASE_INFO(rb_vfunc_info);
|
222
|
+
gtype = NUM2LONG(rb_gtype);
|
223
|
+
g_assert(G_TYPE_IS_CLASSED(gtype));
|
224
|
+
|
225
|
+
find_vfunc_info(vfunc_info, gtype, &implementor_vtable, &field_info);
|
226
|
+
|
227
|
+
if (field_info != NULL) {
|
228
|
+
GITypeInfo *type_info = NULL;
|
229
|
+
GIBaseInfo *interface_info = NULL;
|
230
|
+
RBGIVFuncCallbackData *data = NULL;
|
231
|
+
gint offset = 0;
|
232
|
+
gpointer *method_ptr = NULL;
|
233
|
+
|
234
|
+
type_info = g_field_info_get_type(field_info);
|
235
|
+
|
236
|
+
interface_info = g_type_info_get_interface(type_info);
|
237
|
+
g_assert(g_base_info_get_type(interface_info) == GI_INFO_TYPE_CALLBACK);
|
238
|
+
|
239
|
+
data = ALLOC(RBGIVFuncCallbackData);
|
240
|
+
data->name = rb_name;
|
241
|
+
data->callable_info = g_base_info_ref(interface_info);
|
242
|
+
data->closure = g_callable_info_prepare_closure(
|
243
|
+
interface_info, &(data->cif), ffi_callback, data);
|
244
|
+
|
245
|
+
if (data->closure) {
|
246
|
+
offset = g_field_info_get_offset(field_info);
|
247
|
+
method_ptr = G_STRUCT_MEMBER_P(implementor_vtable, offset);
|
248
|
+
|
249
|
+
*method_ptr = data->closure;
|
250
|
+
}
|
251
|
+
|
252
|
+
g_base_info_unref (interface_info);
|
253
|
+
g_base_info_unref (type_info);
|
254
|
+
g_base_info_unref (field_info);
|
255
|
+
}
|
256
|
+
|
257
|
+
return Qnil;
|
258
|
+
}
|
259
|
+
|
33
260
|
void
|
34
261
|
Init_gobject_introspection(void)
|
35
262
|
{
|
36
263
|
VALUE RG_TARGET_NAMESPACE;
|
37
264
|
|
265
|
+
id_send = rb_intern("__send__");
|
266
|
+
|
38
267
|
{
|
39
268
|
const char *rb_gi_debug_env = getenv("RB_GI_DEBUG");
|
40
269
|
if (rb_gi_debug_env && strcmp(rb_gi_debug_env, "yes") == 0) {
|
@@ -59,4 +288,6 @@ Init_gobject_introspection(void)
|
|
59
288
|
rb_gi_loader_init(RG_TARGET_NAMESPACE);
|
60
289
|
|
61
290
|
rb_gi_callback_init(RG_TARGET_NAMESPACE);
|
291
|
+
|
292
|
+
rb_define_module_function(RG_TARGET_NAMESPACE, "hook_up_vfunc", rb_gi_hook_up_vfunc, 3);
|
62
293
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2012-
|
1
|
+
# Copyright (C) 2012-2021 Ruby-GNOME Project Team
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -216,6 +216,7 @@ module GObjectIntrospection
|
|
216
216
|
klass = self.class.define_class(info.gtype,
|
217
217
|
rubyish_class_name(info),
|
218
218
|
@base_module)
|
219
|
+
load_virtual_functions(info, klass)
|
219
220
|
load_fields(info, klass)
|
220
221
|
load_methods(info, klass)
|
221
222
|
end
|
@@ -338,6 +339,20 @@ module GObjectIntrospection
|
|
338
339
|
end
|
339
340
|
end
|
340
341
|
|
342
|
+
def load_virtual_functions(info, klass)
|
343
|
+
klass.extend(VirtualFunctionImplementable)
|
344
|
+
gtype_prefix = rubyish_gtype_name(klass.gtype.name)
|
345
|
+
implementor = VirtualFunctionImplementor.new(self.class,
|
346
|
+
gtype_prefix,
|
347
|
+
info.vfuncs)
|
348
|
+
klass.__send__(:initialize_virtual_function_implementable,
|
349
|
+
implementor)
|
350
|
+
end
|
351
|
+
|
352
|
+
def rubyish_gtype_name(name)
|
353
|
+
name.scan(/[A-Z]+[a-z\d]+/).collect(&:downcase).join("_")
|
354
|
+
end
|
355
|
+
|
341
356
|
def initialize_post(object)
|
342
357
|
end
|
343
358
|
|
@@ -546,6 +561,7 @@ module GObjectIntrospection
|
|
546
561
|
self.class.define_interface(info.gtype,
|
547
562
|
rubyish_class_name(info),
|
548
563
|
@base_module)
|
564
|
+
load_virtual_functions(info, interface_module)
|
549
565
|
load_methods(info, interface_module)
|
550
566
|
end
|
551
567
|
|
@@ -708,5 +724,53 @@ module GObjectIntrospection
|
|
708
724
|
"#{@full_method_name}: wrong number of arguments (#{detail})"
|
709
725
|
end
|
710
726
|
end
|
727
|
+
|
728
|
+
class VirtualFunctionImplementor
|
729
|
+
def initialize(loader_class, gtype_prefix, infos)
|
730
|
+
@loader_class = loader_class
|
731
|
+
@gtype_prefix = gtype_prefix
|
732
|
+
@infos = {}
|
733
|
+
prefix = GLib::VIRTUAL_FUNCTION_IMPLEMENTATION_PREFIX
|
734
|
+
infos.each do |info|
|
735
|
+
name = info.name
|
736
|
+
@infos[:"#{prefix}#{name}"] = info
|
737
|
+
@infos[:"#{prefix}#{gtype_prefix}_#{name}"] = info
|
738
|
+
end
|
739
|
+
end
|
740
|
+
|
741
|
+
def implement(implementor_gtype, name)
|
742
|
+
info = @infos[name]
|
743
|
+
return false if info.nil?
|
744
|
+
container = info.container
|
745
|
+
vtable_gtype = container.gtype
|
746
|
+
if container.respond_to?(:class_struct)
|
747
|
+
struct = container.class_struct
|
748
|
+
else
|
749
|
+
return false unless implementor_gtype.type_is_a?(vtable_gtype)
|
750
|
+
struct = container.iface_struct
|
751
|
+
end
|
752
|
+
field = struct.find_field(info.name)
|
753
|
+
@loader_class.implement_virtual_function(field,
|
754
|
+
implementor_gtype,
|
755
|
+
vtable_gtype,
|
756
|
+
name.to_s)
|
757
|
+
true
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
module VirtualFunctionImplementable
|
762
|
+
def initialize_virtual_function_implementable(implementor)
|
763
|
+
@virtual_function_implementor = implementor
|
764
|
+
end
|
765
|
+
|
766
|
+
def implement_virtual_function(implementor_class, name)
|
767
|
+
unless instance_variable_defined?(:@virtual_function_implementor)
|
768
|
+
return false
|
769
|
+
end
|
770
|
+
@virtual_function_implementor.implement(implementor_class.gtype,
|
771
|
+
name)
|
772
|
+
true
|
773
|
+
end
|
774
|
+
end
|
711
775
|
end
|
712
776
|
end
|
data/test/run-test.rb
CHANGED
data/test/test-base-info.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2012 Ruby-
|
1
|
+
# Copyright (C) 2012-2021 Ruby-GNOME Project Team
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -28,4 +28,8 @@ class TestBaseInfo < Test::Unit::TestCase
|
|
28
28
|
def test_namespace
|
29
29
|
assert_equal("GObject", @info.namespace)
|
30
30
|
end
|
31
|
+
|
32
|
+
def test_container
|
33
|
+
assert_equal("Object", @info.vfuncs.first.container.name)
|
34
|
+
end
|
31
35
|
end
|
data/test/test-callable-info.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2012 Ruby-
|
1
|
+
# Copyright (C) 2012-2021 Ruby-GNOME Project Team
|
2
2
|
#
|
3
3
|
# This library is free software; you can redistribute it and/or
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -21,6 +21,12 @@ class TestCallableInfo < Test::Unit::TestCase
|
|
21
21
|
@info = @repository.find("GObject", "signal_name")
|
22
22
|
end
|
23
23
|
|
24
|
+
def test_can_throw_gerror
|
25
|
+
assert do
|
26
|
+
not @info.can_throw_gerror?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
24
30
|
def test_return_type
|
25
31
|
assert_kind_of(GObjectIntrospection::TypeInfo,
|
26
32
|
@info.return_type)
|