gobject-introspection 3.4.9 → 4.0.0

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.
@@ -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