gobject-introspection 3.4.0 → 3.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/ext/gobject-introspection/extconf.rb +1 -4
  3. data/ext/gobject-introspection/rb-gi-argument.c +10 -3
  4. data/ext/gobject-introspection/rb-gi-arguments-in.c +82 -122
  5. data/ext/gobject-introspection/rb-gi-arguments-out.c +31 -11
  6. data/ext/gobject-introspection/rb-gi-arguments.c +217 -18
  7. data/ext/gobject-introspection/rb-gi-base-info.c +11 -1
  8. data/ext/gobject-introspection/rb-gi-callable-info.c +10 -2
  9. data/ext/gobject-introspection/rb-gi-callback.c +156 -2
  10. data/ext/gobject-introspection/rb-gi-conversions.h +6 -6
  11. data/ext/gobject-introspection/rb-gi-interface-info.c +1 -7
  12. data/ext/gobject-introspection/rb-gi-loader.c +58 -10
  13. data/ext/gobject-introspection/rb-gi-object-info.c +11 -1
  14. data/ext/gobject-introspection/rb-gi-private-arguments-in.h +3 -1
  15. data/ext/gobject-introspection/rb-gi-private-arguments.h +6 -2
  16. data/ext/gobject-introspection/rb-gi-private-callback.h +6 -3
  17. data/ext/gobject-introspection/rb-gi-private.h +1 -0
  18. data/ext/gobject-introspection/rb-gi-repository.c +1 -1
  19. data/ext/gobject-introspection/rb-gi-struct-info.c +15 -3
  20. data/ext/gobject-introspection/rb-gi-vfunc-info.c +2 -2
  21. data/ext/gobject-introspection/rb-gobject-introspection.c +231 -0
  22. data/lib/gobject-introspection/loader.rb +66 -2
  23. data/lib/gobject-introspection/type-tag.rb +2 -0
  24. data/test/gobject-introspection-test-utils.rb +2 -2
  25. data/test/run-test.rb +18 -25
  26. data/test/test-base-info.rb +5 -1
  27. data/test/test-callable-info.rb +16 -2
  28. data/test/test-loader.rb +53 -7
  29. data/test/test-object-info.rb +5 -1
  30. data/test/test-struct-info.rb +6 -1
  31. metadata +5 -8
  32. data/ext/gobject-introspection/gobject-introspection-enum-types.c +0 -230
  33. data/ext/gobject-introspection/gobject-introspection-enum-types.h +0 -42
  34. data/ext/gobject-introspection/rbgiversion.h +0 -24
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2019 Ruby-GNOME Project Team
3
+ * Copyright (C) 2019-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
@@ -20,6 +20,8 @@
20
20
 
21
21
  #pragma once
22
22
 
23
+ G_GNUC_INTERNAL VALUE
24
+ rb_gi_arguments_in_to_ruby(RBGIArguments *args);
23
25
  G_GNUC_INTERNAL void
24
26
  rb_gi_arguments_in_init(RBGIArguments *args);
25
27
  G_GNUC_INTERNAL void
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2019 Ruby-GNOME Project Team
3
+ * Copyright (C) 2019-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
@@ -40,6 +40,7 @@ typedef void (*RBGIArgFreeFunc)(RBGIArguments *args,
40
40
 
41
41
  typedef struct {
42
42
  GITypeInfo *info;
43
+ gboolean pointer_p;
43
44
  GITypeTag tag;
44
45
  GIBaseInfo *interface_info;
45
46
  GIInfoType interface_type;
@@ -64,7 +65,6 @@ struct RBGIArgMetadata_ {
64
65
  gboolean array_length_p;
65
66
  gboolean interface_p;
66
67
  gboolean may_be_null_p;
67
- gboolean pointer_p;
68
68
  gboolean caller_allocates_p;
69
69
  gboolean zero_terminated_p;
70
70
  gboolean output_buffer_p;
@@ -101,6 +101,10 @@ G_GNUC_INTERNAL VALUE
101
101
  rb_gi_arguments_get_rb_return_value(RBGIArguments *args,
102
102
  GIArgument *return_value);
103
103
 
104
+ G_GNUC_INTERNAL void
105
+ rb_gi_arguments_fill_raw_out_gerror(RBGIArguments *args,
106
+ VALUE rb_error);
107
+
104
108
  G_GNUC_INTERNAL void
105
109
  rb_gi_arguments_fill_raw_results(RBGIArguments *args,
106
110
  VALUE rb_results,
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2019 Ruby-GNOME Project Team
3
+ * Copyright (C) 2019-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
@@ -22,8 +22,8 @@
22
22
 
23
23
  typedef struct RBGICallback_ {
24
24
  GIArgInfo *arg_info;
25
- GITypeInfo *type_info;
26
25
  GICallbackInfo *callback_info;
26
+ gchar *method_name;
27
27
  ffi_cif cif;
28
28
  ffi_closure *closure;
29
29
  } RBGICallback;
@@ -34,8 +34,11 @@ rb_gi_callback_init(VALUE rb_mGI);
34
34
  G_GNUC_INTERNAL gpointer
35
35
  rb_gi_callback_find(GIArgInfo *info);
36
36
 
37
+ G_GNUC_INTERNAL RBGICallback *
38
+ rb_gi_callback_new(GICallbackInfo *callback_info,
39
+ const gchar *method_name);
40
+
37
41
  G_GNUC_INTERNAL RBGICallbackData *
38
42
  rb_gi_callback_data_new(RBGIArguments *args,
39
43
  RBGICallback *callback,
40
44
  RBGIArgMetadata *metadata);
41
-
@@ -22,6 +22,7 @@
22
22
 
23
23
  #include <ruby.h>
24
24
  #include <rbgobject.h>
25
+ #include <rbglib2conversions.h>
25
26
  #include <glib-enum-types.h>
26
27
 
27
28
  #include <girffi.h>
@@ -228,7 +228,7 @@ rg_find(int argc, VALUE *argv, VALUE self)
228
228
  VALUE rb_gtype;
229
229
  GType gtype;
230
230
  rb_gtype = argv[0];
231
- gtype = NUM2UINT(rb_gtype);
231
+ gtype = rbgobj_gtype_from_ruby(rb_gtype);
232
232
  info = g_irepository_find_by_gtype(SELF(self), gtype);
233
233
  } else {
234
234
  VALUE rb_namespace, rb_name;
@@ -1,6 +1,6 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- * Copyright (C) 2012-2019 Ruby-GNOME Project Team
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
@@ -84,7 +84,7 @@ rb_gi_struct_get_raw(VALUE rb_struct, GType gtype)
84
84
  if (rb_respond_to(rb_struct_class, rb_intern("gtype"))) {
85
85
  VALUE rb_gtype;
86
86
  rb_gtype = rb_funcall(rb_struct_class, rb_intern("gtype"), 0);
87
- gtype = NUM2ULONG(rb_funcall(rb_gtype, rb_intern("to_i"), 0));
87
+ gtype = rbgobj_gtype_from_ruby(rb_gtype);
88
88
  }
89
89
  }
90
90
  if (gtype == G_TYPE_NONE) {
@@ -146,7 +146,7 @@ rb_gi_struct_info_to_ruby(GIStructInfo *info,
146
146
  GType gtype;
147
147
 
148
148
  rb_gtype = rb_funcall(rb_class, rb_intern("gtype"), 0);
149
- gtype = NUM2ULONG(rb_funcall(rb_gtype, rb_intern("to_i"), 0));
149
+ gtype = rbgobj_gtype_from_ruby(rb_gtype);
150
150
  return BOXED2RVAL(object, gtype);
151
151
  }
152
152
 
@@ -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-GNOME2 Project Team
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) RVAL2GI_BASE_INFO(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-2019 Ruby-GNOME Project Team
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
 
@@ -681,10 +697,10 @@ module GObjectIntrospection
681
697
  def normalize_arguments!(arguments, abort_tag)
682
698
  arguments.size.times do |i|
683
699
  argument = arguments[i]
684
- next if argument.nil?
685
700
  type = @in_arg_types[i]
686
701
  converted_argument = type.try_convert(argument)
687
702
  if converted_argument.nil?
703
+ next if argument.nil?
688
704
  if abort_tag
689
705
  throw(abort_tag)
690
706
  elsif @on_invalid == :fallback
@@ -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