gobject-introspection 3.4.0 → 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.
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