gobject-introspection 3.4.9 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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-2022 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
@@ -50,12 +50,15 @@
50
50
  # define RB_TYPE_P(object, type) (TYPE(object) == type)
51
51
  #endif
52
52
 
53
+ /* GLib 2.60 or later defines this. */
54
+ #ifndef G_GNUC_FALLTHROUGH
55
+ # define G_GNUC_FALLTHROUGH
56
+ #endif
57
+
53
58
  extern void Init_gobject_introspection(void);
54
59
 
55
60
  gboolean rb_gi_is_debug_mode(void);
56
61
 
57
- void rb_gi_argument_init (void);
58
-
59
62
  void rb_gi_type_tag_init (VALUE rb_mGI);
60
63
  void rb_gi_base_info_init (VALUE rb_mGI);
61
64
  void rb_gi_callable_info_init (VALUE rb_mGI,
@@ -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-2022 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
@@ -39,228 +39,12 @@ rb_gi_is_debug_mode(void)
39
39
  return is_debug_mode;
40
40
  }
41
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
-
260
42
  void
261
43
  Init_gobject_introspection(void)
262
44
  {
263
- VALUE RG_TARGET_NAMESPACE;
45
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
46
+ rb_ext_ractor_safe(true);
47
+ #endif
264
48
 
265
49
  id_send = rb_intern("__send__");
266
50
 
@@ -271,7 +55,7 @@ Init_gobject_introspection(void)
271
55
  }
272
56
  }
273
57
 
274
- RG_TARGET_NAMESPACE = rb_define_module("GObjectIntrospection");
58
+ VALUE RG_TARGET_NAMESPACE = rb_define_module("GObjectIntrospection");
275
59
 
276
60
  rb_define_const(RG_TARGET_NAMESPACE, "BUILD_VERSION",
277
61
  rb_ary_new3(3,
@@ -279,8 +63,6 @@ Init_gobject_introspection(void)
279
63
  INT2FIX(GI_MINOR_VERSION),
280
64
  INT2FIX(GI_MICRO_VERSION)));
281
65
 
282
- rb_gi_argument_init();
283
-
284
66
  rb_gi_array_type_init(RG_TARGET_NAMESPACE);
285
67
  rb_gi_type_tag_init(RG_TARGET_NAMESPACE);
286
68
  rb_gi_base_info_init(RG_TARGET_NAMESPACE);
@@ -288,6 +70,4 @@ Init_gobject_introspection(void)
288
70
  rb_gi_loader_init(RG_TARGET_NAMESPACE);
289
71
 
290
72
  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);
293
73
  }
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2019 Ruby-GNOME Project Team
1
+ # Copyright (C) 2019-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
@@ -18,7 +18,7 @@ module GObjectIntrospection
18
18
  class FunctionInfo
19
19
  def inspect
20
20
  super.gsub(/>\z/) do
21
- " unlock_gvl?=#{unlock_gvl?.inspect}>"
21
+ " lock_gvl_default=#{lock_gvl?.inspect}>"
22
22
  end
23
23
  end
24
24
  end
@@ -24,6 +24,9 @@ module GObjectIntrospection
24
24
  loader.version = options[:version]
25
25
  loader.load(namespace)
26
26
  end
27
+
28
+ def initialize_instance_post(object)
29
+ end
27
30
  end
28
31
 
29
32
  attr_accessor :version
@@ -35,14 +38,16 @@ module GObjectIntrospection
35
38
  def load(namespace)
36
39
  repository = Repository.default
37
40
  repository.require(namespace, @version)
38
- pre_load(repository, namespace)
39
- repository.each(namespace) do |info|
40
- load_info(info) if info.is_a?(InterfaceInfo)
41
- end
42
- repository.each(namespace) do |info|
43
- load_info(info) unless info.is_a?(InterfaceInfo)
41
+ prepare_class(@base_module) do
42
+ pre_load(repository, namespace)
43
+ repository.each(namespace) do |info|
44
+ load_info(info) if info.is_a?(InterfaceInfo)
45
+ end
46
+ repository.each(namespace) do |info|
47
+ load_info(info) unless info.is_a?(InterfaceInfo)
48
+ end
49
+ post_load(repository, namespace)
44
50
  end
45
- post_load(repository, namespace)
46
51
  end
47
52
 
48
53
  private
@@ -85,23 +90,28 @@ module GObjectIntrospection
85
90
  end
86
91
 
87
92
  def define_module_function(target_module, name, function_info)
88
- function_info.unlock_gvl = should_unlock_gvl?(function_info, target_module)
93
+ prepare_function_info_lock_gvl(function_info, target_module)
89
94
  full_method_name = "#{target_module}\#.#{name}"
90
95
  invoker = Invoker.new(function_info, name, full_method_name)
91
- target_module.module_eval do
92
- define_method(name) do |*arguments, &block|
93
- invoker.invoke(nil, arguments, block)
96
+ target_module::INVOKERS[name] = invoker
97
+ target_module.module_eval(<<-DEFINE_METHOD, __FILE__, __LINE__ + 1)
98
+ def #{name}(*arguments, &block)
99
+ INVOKERS["#{name}"].invoke(nil, arguments, block)
94
100
  end
95
- module_function(name)
96
- end
101
+ module_function(:#{name})
102
+ DEFINE_METHOD
97
103
  end
98
104
 
99
105
  def define_singleton_method(klass, name, info)
100
- info.unlock_gvl = should_unlock_gvl?(info, klass)
106
+ prepare_function_info_lock_gvl(info, klass)
101
107
  invoker = Invoker.new(info, name, "#{klass}.#{name}")
102
- klass.singleton_class.__send__(:define_method, name) do |*arguments, &block|
103
- invoker.invoke(nil, arguments, block)
104
- end
108
+ singleton_class = klass.singleton_class
109
+ singleton_class::INVOKERS[name] = invoker
110
+ singleton_class.class_eval(<<-DEFINE_METHOD, __FILE__, __LINE__ + 1)
111
+ def #{name}(*arguments, &block)
112
+ INVOKERS["#{name}"].invoke(nil, arguments, block)
113
+ end
114
+ DEFINE_METHOD
105
115
  end
106
116
 
107
117
  def define_struct(info, options={})
@@ -116,8 +126,10 @@ module GObjectIntrospection
116
126
  :parent => options[:parent],
117
127
  :size => size)
118
128
  end
119
- load_fields(info, klass)
120
- load_methods(info, klass)
129
+ prepare_class(klass) do
130
+ load_fields(info, klass)
131
+ load_methods(info, klass)
132
+ end
121
133
  end
122
134
 
123
135
  def load_struct_info(info)
@@ -129,7 +141,12 @@ module GObjectIntrospection
129
141
  end
130
142
  unless method_infos.empty?
131
143
  base_class = @base_module.const_get(base_class_name)
132
- load_methods_method(method_infos, base_class.singleton_class)
144
+ singleton_class = base_class.singleton_class
145
+ invokers = singleton_class::INVOKERS.dup
146
+ singleton_class.__send__(:remove_const, :INVOKERS)
147
+ singleton_class.const_set(:INVOKERS, invokers)
148
+ load_methods_method(method_infos, singleton_class)
149
+ Ractor.make_shareable(singleton_class::INVOKERS) if defined?(Ractor)
133
150
  end
134
151
  else
135
152
  return if info.gtype_struct?
@@ -152,7 +169,9 @@ module GObjectIntrospection
152
169
  end
153
170
 
154
171
  def load_enum_value(value_info, enum_module)
155
- enum_module.const_set(value_info.name.upcase, value_info.value)
172
+ value = value_info.value
173
+ Ractor.make_shareable(value) if defined?(Ractor)
174
+ enum_module.const_set(value_info.name.upcase, value)
156
175
  end
157
176
 
158
177
  def define_enum(info)
@@ -216,9 +235,11 @@ module GObjectIntrospection
216
235
  klass = self.class.define_class(info.gtype,
217
236
  rubyish_class_name(info),
218
237
  @base_module)
219
- load_virtual_functions(info, klass)
220
- load_fields(info, klass)
221
- load_methods(info, klass)
238
+ prepare_class(klass) do
239
+ load_virtual_functions(info, klass)
240
+ load_fields(info, klass)
241
+ load_methods(info, klass)
242
+ end
222
243
  end
223
244
 
224
245
  def load_fields(info, klass)
@@ -300,43 +321,46 @@ module GObjectIntrospection
300
321
  def load_methods_constructor(infos, klass)
301
322
  return if infos.empty?
302
323
 
303
- call_initialize_post = lambda do |object|
304
- initialize_post(object)
305
- end
306
- invokers = []
324
+ klass.const_set(:LOADER_CLASS, self.class)
325
+ invokers = {}
326
+ klass.const_set(:INITIALIZE_INVOKERS, invokers)
307
327
  infos.each do |info|
308
328
  name = "initialize_#{info.name}"
309
- info.unlock_gvl = should_unlock_gvl?(info, klass)
329
+ prepare_function_info_lock_gvl(info, klass)
310
330
  invoker = Invoker.new(info, name, "#{klass}\##{name}")
311
- invokers << invoker
312
- klass.__send__(:define_method, name) do |*arguments, &block|
313
- invoker.invoke(self, arguments, block)
314
- call_initialize_post.call(self)
315
- end
316
- klass.__send__(:private, name)
317
- end
318
-
319
- initialize = lambda do |receiver, arguments, block|
320
- invokers.each do |invoker|
321
- catch do |tag|
322
- invoker.invoke(receiver, arguments.dup, block, tag)
323
- call_initialize_post.call(receiver)
324
- return
331
+ invokers[name] = invoker
332
+ klass.class_eval(<<-DEFINE_METHOD, __FILE__, __LINE__ + 1)
333
+ def #{name}(*arguments, &block)
334
+ invoker = INITIALIZE_INVOKERS["#{name}"]
335
+ invoker.invoke(self, arguments, block)
336
+ LOADER_CLASS.initialize_instance_post(self)
325
337
  end
338
+ private :#{name}
339
+ DEFINE_METHOD
340
+ end
341
+
342
+ klass.class_eval(<<-DEFINE_METHOD, __FILE__, __LINE__ + 1)
343
+ def initialize(*arguments, &block)
344
+ invokers = INITIALIZE_INVOKERS
345
+ invokers.values.each do |invoker|
346
+ catch do |tag|
347
+ invoker.invoke(self, arguments.dup, block, tag)
348
+ LOADER_CLASS.initialize_instance_post(self)
349
+ return
350
+ end
351
+ end
352
+ message = "wrong arguments: "
353
+ message << "\#{self.class.name}#initialize("
354
+ message << arguments.collect(&:inspect).join(", ")
355
+ message << "): "
356
+ message << "available signatures"
357
+ invokers.each_value do |invoker|
358
+ message << ": \#{invoker.signature}"
359
+ end
360
+ raise ArgumentError, message
326
361
  end
327
- message = "wrong arguments: "
328
- message << "#{klass.name}#initialize("
329
- message << arguments.collect(&:inspect).join(", ")
330
- message << "): "
331
- message << "available signatures"
332
- invokers.each do |invoker|
333
- message << ": #{invoker.signature}"
334
- end
335
- raise ArgumentError, message
336
- end
337
- klass.__send__(:define_method, "initialize") do |*arguments, &block|
338
- initialize.call(self, arguments, block)
339
- end
362
+ DEFINE_METHOD
363
+ Ractor.make_shareable(klass::INITIALIZE_INVOKERS) if defined?(Ractor)
340
364
  end
341
365
 
342
366
  def load_virtual_functions(info, klass)
@@ -353,9 +377,6 @@ module GObjectIntrospection
353
377
  name.scan(/[A-Z]+[a-z\d]+/).collect(&:downcase).join("_")
354
378
  end
355
379
 
356
- def initialize_post(object)
357
- end
358
-
359
380
  def rubyish_method_name(function_info, options={})
360
381
  name = function_info.name
361
382
  if options[:prefix]
@@ -498,8 +519,12 @@ module GObjectIntrospection
498
519
  end
499
520
  end
500
521
 
501
- def should_unlock_gvl?(function_info, klass)
502
- false
522
+ def prepare_function_info_lock_gvl(function_info, target_module)
523
+ # For backward compatiblity
524
+ if respond_to?(:should_unlock_gvl?)
525
+ function_info.lock_gvl_default =
526
+ !should_unlock_gvl?(function_info, target_module)
527
+ end
503
528
  end
504
529
 
505
530
  def load_methods_method(infos, klass)
@@ -522,12 +547,18 @@ module GObjectIntrospection
522
547
  end
523
548
 
524
549
  def define_method(info, klass, method_name)
525
- info.unlock_gvl = should_unlock_gvl?(info, klass)
550
+ return if method_name.empty?
551
+ prepare_function_info_lock_gvl(info, klass)
526
552
  remove_existing_method(klass, method_name)
527
553
  invoker = Invoker.new(info, method_name, "#{klass}\##{method_name}")
528
- klass.__send__(:define_method, method_name) do |*arguments, &block|
529
- invoker.invoke(self, arguments, block)
530
- end
554
+ invokers = klass::INVOKERS
555
+ invokers[method_name] = invoker
556
+ klass.class_eval(<<-DEFINE_METHOD, __FILE__, __LINE__ + 1)
557
+ def #{method_name}(*arguments, &block)
558
+ invoker = INVOKERS["#{method_name}"]
559
+ invoker.invoke(self, arguments, block)
560
+ end
561
+ DEFINE_METHOD
531
562
  end
532
563
 
533
564
  def define_equal_style_setter(info, klass, method_name)
@@ -540,9 +571,11 @@ module GObjectIntrospection
540
571
 
541
572
  def define_inspect(info, klass, method_name)
542
573
  if method_name == "to_s" and info.n_args.zero?
543
- klass.__send__(:define_method, "inspect") do ||
544
- super().gsub(/\>\z/) {" #{to_s}>"}
545
- end
574
+ klass.class_eval(<<-DEFINE_METHOD, __FILE__, __LINE__ + 1)
575
+ def inspect
576
+ super.gsub(/>\\z/) {" \#{to_s}>"}
577
+ end
578
+ DEFINE_METHOD
546
579
  end
547
580
  end
548
581
 
@@ -561,8 +594,10 @@ module GObjectIntrospection
561
594
  self.class.define_interface(info.gtype,
562
595
  rubyish_class_name(info),
563
596
  @base_module)
564
- load_virtual_functions(info, interface_module)
565
- load_methods(info, interface_module)
597
+ prepare_class(interface_module) do
598
+ load_virtual_functions(info, interface_module)
599
+ load_methods(info, interface_module)
600
+ end
566
601
  end
567
602
 
568
603
  def load_constant_info(info)
@@ -576,8 +611,44 @@ module GObjectIntrospection
576
611
  def load_union_info(info)
577
612
  return if info.gtype == GLib::Type::NONE
578
613
  klass = self.class.define_class(info.gtype, info.name, @base_module)
579
- load_fields(info, klass)
580
- load_methods(info, klass)
614
+ prepare_class(klass) do
615
+ load_fields(info, klass)
616
+ load_methods(info, klass)
617
+ end
618
+ end
619
+
620
+ def prepare_class(klass)
621
+ pre_prepare_class(klass)
622
+ yield
623
+ post_prepare_class(klass)
624
+ end
625
+
626
+ def pre_prepare_class(klass)
627
+ klass.const_set(:INVOKERS, {})
628
+ klass.singleton_class.const_set(:INVOKERS, {})
629
+ end
630
+
631
+ def post_prepare_class(klass)
632
+ return unless defined?(Ractor)
633
+ Ractor.make_shareable(klass::INVOKERS)
634
+ Ractor.make_shareable(klass.singleton_class::INVOKERS)
635
+ end
636
+
637
+ def define_methods_module(name)
638
+ mod = Module.new
639
+ @base_module.const_set(name, mod)
640
+ mod.const_set(:INVOKERS, {})
641
+ mod
642
+ end
643
+
644
+ def apply_methods_module(mod, target)
645
+ target.include(mod)
646
+ post_methods_module(mod)
647
+ end
648
+
649
+ def post_methods_module(mod)
650
+ return unless defined?(Ractor)
651
+ Ractor.make_shareable(mod::INVOKERS)
581
652
  end
582
653
 
583
654
  class Invoker
@@ -586,6 +657,7 @@ module GObjectIntrospection
586
657
  @method_name = method_name
587
658
  @full_method_name = full_method_name
588
659
  @prepared = false
660
+ ensure_prepared if defined?(Ractor)
589
661
  end
590
662
 
591
663
  def invoke(receiver, arguments, block, abort_tag=nil)
@@ -645,10 +717,13 @@ module GObjectIntrospection
645
717
  @valid_n_args_range = (@n_required_in_args..@n_in_args)
646
718
 
647
719
  @in_arg_types = []
720
+ @in_arg_nils = []
648
721
  @in_arg_nil_indexes = []
649
722
  @in_args.each_with_index do |arg, i|
650
723
  @in_arg_types << arg.type
651
- @in_arg_nil_indexes << i if arg.may_be_null?
724
+ may_be_null = arg.may_be_null?
725
+ @in_arg_nils << may_be_null
726
+ @in_arg_nil_indexes << i if may_be_null
652
727
  end
653
728
 
654
729
  @function_info_p = (@info.class == FunctionInfo)
@@ -700,7 +775,7 @@ module GObjectIntrospection
700
775
  type = @in_arg_types[i]
701
776
  converted_argument = type.try_convert(argument)
702
777
  if converted_argument.nil?
703
- next if argument.nil?
778
+ next if argument.nil? and @in_arg_nils[i]
704
779
  if abort_tag
705
780
  throw(abort_tag)
706
781
  elsif @on_invalid == :fallback
@@ -769,7 +844,6 @@ module GObjectIntrospection
769
844
  end
770
845
  @virtual_function_implementor.implement(implementor_class.gtype,
771
846
  name)
772
- true
773
847
  end
774
848
  end
775
849
  end