gir_ffi 0.13.0 → 0.13.1

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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +10 -0
  3. data/lib/ffi-glib/array.rb +2 -2
  4. data/lib/ffi-glib/array_methods.rb +1 -0
  5. data/lib/ffi-glib/list_methods.rb +3 -2
  6. data/lib/ffi-glib/main_loop.rb +2 -0
  7. data/lib/ffi-glib/ptr_array.rb +2 -2
  8. data/lib/ffi-gobject.rb +3 -11
  9. data/lib/ffi-gobject/closure.rb +1 -0
  10. data/lib/ffi-gobject/object.rb +30 -16
  11. data/lib/ffi-gobject/object_class.rb +2 -2
  12. data/lib/ffi-gobject/ruby_closure.rb +2 -2
  13. data/lib/ffi-gobject/value.rb +2 -1
  14. data/lib/ffi-gobject_introspection/i_arg_info.rb +11 -11
  15. data/lib/ffi-gobject_introspection/i_base_info.rb +12 -10
  16. data/lib/ffi-gobject_introspection/i_callable_info.rb +8 -8
  17. data/lib/ffi-gobject_introspection/i_enum_info.rb +5 -5
  18. data/lib/ffi-gobject_introspection/i_field_info.rb +4 -4
  19. data/lib/ffi-gobject_introspection/i_function_info.rb +2 -2
  20. data/lib/ffi-gobject_introspection/i_interface_info.rb +15 -15
  21. data/lib/ffi-gobject_introspection/i_object_info.rb +22 -22
  22. data/lib/ffi-gobject_introspection/i_property_info.rb +2 -2
  23. data/lib/ffi-gobject_introspection/i_registered_type_info.rb +3 -3
  24. data/lib/ffi-gobject_introspection/i_repository.rb +16 -10
  25. data/lib/ffi-gobject_introspection/i_struct_info.rb +11 -7
  26. data/lib/ffi-gobject_introspection/i_type_info.rb +8 -8
  27. data/lib/ffi-gobject_introspection/i_union_info.rb +7 -7
  28. data/lib/ffi-gobject_introspection/i_value_info.rb +1 -1
  29. data/lib/ffi-gobject_introspection/strv.rb +1 -0
  30. data/lib/gir_ffi-base/gobject.rb +5 -0
  31. data/lib/gir_ffi-base/gobject/lib.rb +4 -0
  32. data/lib/gir_ffi/boolean.rb +2 -2
  33. data/lib/gir_ffi/builders/argument_builder.rb +41 -14
  34. data/lib/gir_ffi/builders/argument_builder_collection.rb +17 -4
  35. data/lib/gir_ffi/builders/base_argument_builder.rb +12 -16
  36. data/lib/gir_ffi/builders/callback_argument_builder.rb +1 -1
  37. data/lib/gir_ffi/builders/callback_builder.rb +1 -1
  38. data/lib/gir_ffi/builders/closure_to_pointer_convertor.rb +2 -9
  39. data/lib/gir_ffi/builders/field_builder.rb +11 -9
  40. data/lib/gir_ffi/builders/module_builder.rb +2 -1
  41. data/lib/gir_ffi/builders/object_builder.rb +21 -12
  42. data/lib/gir_ffi/builders/pointer_value_convertor.rb +8 -6
  43. data/lib/gir_ffi/builders/property_builder.rb +4 -2
  44. data/lib/gir_ffi/builders/registered_type_builder.rb +30 -19
  45. data/lib/gir_ffi/builders/return_value_builder.rb +2 -2
  46. data/lib/gir_ffi/builders/ruby_to_c_convertor.rb +2 -0
  47. data/lib/gir_ffi/builders/signal_closure_builder.rb +1 -1
  48. data/lib/gir_ffi/builders/struct_builder.rb +7 -8
  49. data/lib/gir_ffi/builders/unintrospectable_builder.rb +4 -1
  50. data/lib/gir_ffi/builders/user_defined_builder.rb +31 -95
  51. data/lib/gir_ffi/builders/vfunc_builder.rb +1 -1
  52. data/lib/gir_ffi/builders/with_layout.rb +3 -1
  53. data/lib/gir_ffi/callback_base.rb +3 -2
  54. data/lib/gir_ffi/class_base.rb +5 -0
  55. data/lib/gir_ffi/enum_like_base.rb +9 -5
  56. data/lib/gir_ffi/error_argument_info.rb +1 -1
  57. data/lib/gir_ffi/ffi_ext/pointer.rb +1 -4
  58. data/lib/gir_ffi/field_argument_info.rb +1 -1
  59. data/lib/gir_ffi/in_pointer.rb +36 -23
  60. data/lib/gir_ffi/info_ext/i_arg_info.rb +2 -0
  61. data/lib/gir_ffi/info_ext/i_callback_info.rb +4 -0
  62. data/lib/gir_ffi/info_ext/i_registered_type_info.rb +4 -0
  63. data/lib/gir_ffi/info_ext/i_type_info.rb +3 -27
  64. data/lib/gir_ffi/info_ext/safe_function_name.rb +1 -0
  65. data/lib/gir_ffi/interface_base.rb +5 -0
  66. data/lib/gir_ffi/module_base.rb +1 -0
  67. data/lib/gir_ffi/object_base.rb +10 -0
  68. data/lib/gir_ffi/object_store.rb +2 -0
  69. data/lib/gir_ffi/receiver_argument_info.rb +1 -1
  70. data/lib/gir_ffi/return_value_info.rb +1 -1
  71. data/lib/gir_ffi/sized_array.rb +7 -14
  72. data/lib/gir_ffi/struct_like_base.rb +3 -0
  73. data/lib/gir_ffi/type_map.rb +21 -0
  74. data/lib/gir_ffi/user_defined_object_info.rb +6 -2
  75. data/lib/gir_ffi/user_defined_property_info.rb +113 -71
  76. data/lib/gir_ffi/version.rb +1 -1
  77. data/lib/gir_ffi/zero_terminated.rb +26 -1
  78. data/tasks/test.rake +1 -0
  79. data/test/ffi-gobject_introspection/i_repository_test.rb +1 -2
  80. data/test/gir_ffi/builder_test.rb +13 -7
  81. data/test/gir_ffi/builders/argument_builder_test.rb +1 -5
  82. data/test/gir_ffi/builders/callback_return_value_builder_test.rb +1 -1
  83. data/test/gir_ffi/builders/field_builder_test.rb +20 -20
  84. data/test/gir_ffi/builders/return_value_builder_test.rb +1 -1
  85. data/test/gir_ffi/builders/signal_closure_builder_test.rb +1 -1
  86. data/test/gir_ffi/builders/unintrospectable_boxed_builder_test.rb +1 -1
  87. data/test/gir_ffi/builders/unintrospectable_builder_test.rb +2 -2
  88. data/test/gir_ffi/builders/vfunc_builder_test.rb +1 -1
  89. data/test/gir_ffi/enum_base_test.rb +43 -0
  90. data/test/gir_ffi/info_ext/i_type_info_test.rb +3 -9
  91. data/test/gir_ffi/object_base_test.rb +30 -0
  92. data/test/gir_ffi/sized_array_test.rb +0 -9
  93. data/test/gir_ffi/user_defined_object_info_test.rb +4 -6
  94. data/test/gir_ffi/user_defined_property_info_test.rb +6 -5
  95. data/test/gir_ffi/zero_terminated_test.rb +22 -0
  96. data/test/gir_ffi_test_helper.rb +2 -0
  97. data/test/integration/generated_gimarshallingtests_test.rb +1 -0
  98. data/test/integration/generated_gio_test.rb +5 -6
  99. data/test/integration/generated_gobject_test.rb +1 -1
  100. data/test/integration/generated_gtop_test.rb +3 -1
  101. data/test/integration/generated_regress_test.rb +3 -4
  102. metadata +3 -2
@@ -405,7 +405,7 @@ describe GirFFI::Builders::ReturnValueBuilder do
405
405
  let(:type_info) { callback_info.args[0].argument_type }
406
406
 
407
407
  before do
408
- builder.closure = true
408
+ builder.mark_as_user_data :dummy
409
409
  end
410
410
 
411
411
  it 'fetches the stored object in #post_conversion' do
@@ -12,7 +12,7 @@ describe GirFFI::Builders::SignalClosureBuilder do
12
12
 
13
13
  it 'builds a descendant of RubyClosure' do
14
14
  klass = builder.build_class
15
- klass.ancestors.must_include GObject::RubyClosure
15
+ klass.superclass.must_equal GObject::RubyClosure
16
16
  end
17
17
  end
18
18
 
@@ -23,7 +23,7 @@ describe GirFFI::Builders::UnintrospectableBoxedBuilder do
23
23
  end
24
24
 
25
25
  it 'builds a class derived from GirFFI::BoxedBase' do
26
- boxed_class.ancestors.must_include GirFFI::BoxedBase
26
+ boxed_class.superclass.must_equal GirFFI::BoxedBase
27
27
  end
28
28
 
29
29
  it 'returns the same class when built again' do
@@ -21,11 +21,11 @@ describe GirFFI::Builders::UnintrospectableBuilder do
21
21
  end
22
22
 
23
23
  it 'builds a class derived from GObject::Object' do
24
- assert_includes @klass.ancestors, GObject::Object
24
+ assert_includes @klass.registered_ancestors, GObject::Object
25
25
  end
26
26
 
27
27
  it 'builds a class derived from Gio::File' do
28
- assert_includes @klass.ancestors, Gio::File
28
+ assert_includes @klass.registered_ancestors, Gio::File
29
29
  end
30
30
 
31
31
  it 'returns the same class when built again' do
@@ -40,7 +40,7 @@ describe GirFFI::Builders::VFuncBuilder do
40
40
  def self.call_with_argument_mapping(_proc, _instance)
41
41
  _v1 = GIMarshallingTests::Object.wrap(_instance)
42
42
  _v2 = _proc.call(_v1)
43
- _v3 = GIMarshallingTests::Enum.from(_v2)
43
+ _v3 = GIMarshallingTests::Enum.to_int(_v2)
44
44
  return _v3
45
45
  end
46
46
  CODE
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gir_ffi_test_helper'
4
+
5
+ GirFFI.setup :Regress
6
+
7
+ describe GirFFI::EnumBase do
8
+ describe '.wrap' do
9
+ it 'converts an integer to a symbol if possible' do
10
+ Regress::TestEnum.wrap(1).must_equal :value2
11
+ end
12
+
13
+ it 'passes an integer if it cannot be converted' do
14
+ Regress::TestEnum.wrap(32).must_equal 32
15
+ end
16
+
17
+ it 'passes a known symbol untouched' do
18
+ Regress::TestEnum.wrap(:value1).must_equal :value1
19
+ end
20
+
21
+ it 'passes an unknown symbol untouched' do
22
+ Regress::TestEnum.wrap(:foo).must_equal :foo
23
+ end
24
+ end
25
+
26
+ describe '.to_int' do
27
+ it 'passes a known integer untouched' do
28
+ Regress::TestEnum.to_int(1).must_equal 1
29
+ end
30
+
31
+ it 'passes an unknown integer untouched' do
32
+ Regress::TestEnum.to_int(32).must_equal 32
33
+ end
34
+
35
+ it 'convertes a known symbol to an integer' do
36
+ Regress::TestEnum.to_int(:value1).must_equal 0
37
+ end
38
+
39
+ it 'raises an error for an unknown symbol' do
40
+ -> { Regress::TestEnum.to_int(:foo) }.must_raise ArgumentError
41
+ end
42
+ end
43
+ end
@@ -267,16 +267,10 @@ describe GirFFI::InfoExt::ITypeInfo do
267
267
  allow(type_info).to receive(:pointer?).and_return false
268
268
  end
269
269
 
270
- it 'correctly maps a :union argument to :pointer' do
271
- allow(iface_info).to receive(:info_type).and_return :union
270
+ it 'delegates to interface info' do
271
+ allow(iface_info).to receive(:to_callback_ffi_type).and_return :some_ffi_type
272
272
 
273
- type_info.to_callback_ffi_type.must_equal :pointer
274
- end
275
-
276
- it 'correctly maps a :flags argument to :int32' do
277
- allow(iface_info).to receive(:info_type).and_return :flags
278
-
279
- type_info.to_callback_ffi_type.must_equal :int32
273
+ type_info.to_callback_ffi_type.must_equal :some_ffi_type
280
274
  end
281
275
  end
282
276
  end
@@ -31,4 +31,34 @@ describe GirFFI::ObjectBase do
31
31
  second.must_be :eql?, first
32
32
  end
33
33
  end
34
+
35
+ describe '#included_interfaces' do
36
+ let(:base_class) { GIMarshallingTests::Object }
37
+ let(:derived_class) { Class.new(base_class) }
38
+
39
+ before do
40
+ derived_class.class_eval { include GIMarshallingTests::Interface }
41
+ end
42
+
43
+ it 'finds the included interface' do
44
+ derived_class.included_interfaces.must_equal [GIMarshallingTests::Interface]
45
+ end
46
+ end
47
+
48
+ describe '#registered_ancestors' do
49
+ let(:base_class) { GIMarshallingTests::Object }
50
+ let(:derived_class) { Class.new(base_class) }
51
+
52
+ before do
53
+ derived_class.class_eval { include GIMarshallingTests::Interface }
54
+ end
55
+
56
+ it 'finds the ancestor classes and included interface' do
57
+ derived_class.registered_ancestors.
58
+ must_equal [derived_class,
59
+ GIMarshallingTests::Interface,
60
+ GIMarshallingTests::Object,
61
+ GObject::Object]
62
+ end
63
+ end
34
64
  end
@@ -135,15 +135,6 @@ describe GirFFI::SizedArray do
135
135
  arr = GirFFI::SizedArray.copy_from :gint32, 0, nil
136
136
  arr.must_be_nil
137
137
  end
138
-
139
- it 'creates an unowned copy of its argument if given a pointer' do
140
- arr = GirFFI::SizedArray.from :gint32, 3, [3, 2, 1]
141
- arr2 = GirFFI::SizedArray.copy_from :gint32, 3, arr.to_ptr
142
- assert_instance_of GirFFI::SizedArray, arr2
143
- arr2.to_ptr.wont_be :==, arr.to_ptr
144
- arr2.to_ptr.wont_be :autorelease?
145
- arr2.to_a.must_equal [3, 2, 1]
146
- end
147
138
  end
148
139
 
149
140
  describe '#==' do
@@ -19,10 +19,8 @@ describe GirFFI::UserDefinedObjectInfo do
19
19
  let(:foo_spec) { Object.new }
20
20
 
21
21
  it 'adds the passed in property to the list of properties' do
22
- expect(foo_spec).to receive(:get_name).and_return :foo
23
-
24
22
  info.install_property foo_spec
25
- info.properties.map(&:name).must_equal [:foo]
23
+ info.properties.must_equal [foo_spec]
26
24
  end
27
25
  end
28
26
 
@@ -60,12 +58,12 @@ describe GirFFI::UserDefinedObjectInfo do
60
58
  end
61
59
 
62
60
  before do
63
- expect(foo_spec).to receive(:get_name).and_return :foo
64
- expect(bar_spec).to receive(:get_name).and_return :bar
61
+ allow(foo_spec).to receive(:get_name).and_return :foo
62
+ allow(bar_spec).to receive(:get_name).and_return :bar
65
63
  end
66
64
 
67
65
  it 'yields the new object to the block passed' do
68
- info.properties.map(&:name).must_equal [:foo, :bar]
66
+ info.properties.map(&:get_name).must_equal [:foo, :bar]
69
67
  end
70
68
  end
71
69
 
@@ -10,7 +10,8 @@ describe GirFFI::UserDefinedPropertyInfo do
10
10
  1, 3, 2,
11
11
  readable: true, writable: true)
12
12
  end
13
- let(:info) { GirFFI::UserDefinedPropertyInfo.new pspec }
13
+ let(:container) { Object.new }
14
+ let(:info) { GirFFI::UserDefinedPropertyInfo.new pspec, container, 24 }
14
15
 
15
16
  describe '#param_spec' do
16
17
  it 'returns the passed in parameter specification' do
@@ -19,8 +20,8 @@ describe GirFFI::UserDefinedPropertyInfo do
19
20
  end
20
21
 
21
22
  describe '#name' do
22
- it 'returns the name retrieved from the parameter specification' do
23
- info.name.must_equal 'foo-bar'
23
+ it 'returns the accessor name from the parameter specification' do
24
+ info.name.must_equal 'foo_bar'
24
25
  end
25
26
  end
26
27
 
@@ -30,9 +31,9 @@ describe GirFFI::UserDefinedPropertyInfo do
30
31
  end
31
32
  end
32
33
 
33
- describe '#type_tag' do
34
+ describe '#field_type.tag' do
34
35
  it 'returns the mapped type symbol' do
35
- info.type_tag.must_equal :gint
36
+ info.field_type.tag.must_equal :gint
36
37
  end
37
38
  end
38
39
  end
@@ -14,6 +14,20 @@ describe GirFFI::ZeroTerminated do
14
14
  it 'returns a GirFFI::ZeroTerminated object' do
15
15
  result.must_be_instance_of GirFFI::ZeroTerminated
16
16
  end
17
+
18
+ it 'works for Regress::TestEnum from numbers' do
19
+ GirFFI.setup :Regress
20
+ enum_arr = GirFFI::ZeroTerminated.from Regress::TestEnum, [1, -1, 48]
21
+ ptr = enum_arr.to_ptr
22
+ ptr.read_array_of_int32(4).must_equal [1, -1, 48, 0]
23
+ end
24
+
25
+ it 'works for Regress::TestEnum from symbols' do
26
+ GirFFI.setup :Regress
27
+ enum_arr = GirFFI::ZeroTerminated.from Regress::TestEnum, [:value2, :value3, :value4]
28
+ ptr = enum_arr.to_ptr
29
+ ptr.read_array_of_int32(4).must_equal [1, -1, 48, 0]
30
+ end
17
31
  end
18
32
 
19
33
  describe '.wrap' do
@@ -83,4 +97,12 @@ describe GirFFI::ZeroTerminated do
83
97
  it 'includes Enumerable' do
84
98
  GirFFI::ZeroTerminated.must_include Enumerable
85
99
  end
100
+
101
+ describe '#to_a' do
102
+ it 'works for Regress::TestEnum' do
103
+ GirFFI.setup :Regress
104
+ enum_arr = GirFFI::ZeroTerminated.from Regress::TestEnum, [1, 48, -1]
105
+ enum_arr.to_a.must_equal [:value2, :value4, :value3]
106
+ end
107
+ end
86
108
  end
@@ -17,6 +17,7 @@ module GirFFITestExtensions
17
17
 
18
18
  def save_module(name)
19
19
  return unless Object.const_defined? name
20
+
20
21
  puts "Saving #{name} over existing" if SAVED_MODULES.key? name
21
22
  SAVED_MODULES[name] = Object.const_get name
22
23
  Object.send(:remove_const, name)
@@ -25,6 +26,7 @@ module GirFFITestExtensions
25
26
  def restore_module(name)
26
27
  Object.send(:remove_const, name) if Object.const_defined? name
27
28
  return unless SAVED_MODULES.key? name
29
+
28
30
  Object.const_set name, SAVED_MODULES[name]
29
31
  SAVED_MODULES.delete name
30
32
  end
@@ -611,6 +611,7 @@ describe GIMarshallingTests do
611
611
  derived_instance = make_derived_instance do |info|
612
612
  info.install_vfunc_implementation :vfunc_meth_with_err, proc { |_object, x|
613
613
  raise 'This is not the answer!' unless x == 42
614
+
614
615
  true
615
616
  }
616
617
  end
@@ -9,8 +9,10 @@ describe 'The generated Gio module' do
9
9
  describe 'File#new_for_path, a method returning an interface,' do
10
10
  it 'returns an object of a more specific class' do
11
11
  file = Gio::File.new_for_path('/')
12
+ file.class.registered_ancestors.must_equal [file.class, Gio::File, GObject::Object]
13
+
12
14
  refute_instance_of Gio::File, file
13
- assert_includes file.class.ancestors, Gio::File
15
+ assert_includes file.class.registered_ancestors, Gio::File
14
16
  end
15
17
  end
16
18
 
@@ -20,9 +22,7 @@ describe 'The generated Gio module' do
20
22
  end
21
23
 
22
24
  it 'is able to set up a method in a class that is not the first ancestor' do
23
- anc = @it.class.ancestors
24
- assert_equal [Gio::File, GObject::Object], anc[1, 2]
25
-
25
+ refute_defines_instance_method @it.class, :get_qdata
26
26
  refute_defines_instance_method Gio::File, :get_qdata
27
27
  assert_defines_instance_method GObject::Object, :get_qdata
28
28
 
@@ -82,8 +82,7 @@ describe 'The generated Gio module' do
82
82
  describe 'the CharsetConverter class' do
83
83
  it 'includes two interfaces' do
84
84
  klass = Gio::CharsetConverter
85
- assert_includes klass.ancestors, Gio::Converter
86
- assert_includes klass.ancestors, Gio::Initable
85
+ klass.included_interfaces.must_equal [Gio::Initable, Gio::Converter]
87
86
  end
88
87
 
89
88
  it 'allows an instance to find the #reset method' do
@@ -48,7 +48,7 @@ describe GObject do
48
48
  describe GObject::TypeModule do
49
49
  it 'has the GObject::TypePlugin module as an ancestor' do
50
50
  klass = GObject::TypeModule
51
- assert_includes klass.ancestors, GObject::TypePlugin
51
+ assert_includes klass.registered_ancestors, GObject::TypePlugin
52
52
  end
53
53
  end
54
54
 
@@ -15,7 +15,9 @@ describe 'The generated GTop module' do
15
15
 
16
16
  describe 'Glibtop' do
17
17
  it 'is a valid struct class' do
18
- GTop::Glibtop.ancestors.must_include GirFFI::StructBase
18
+ # Superclass is either BoxedBase or StructBase, depending on library
19
+ # versions. This means StructBase is always one of the ancestors.
20
+ assert GTop::Glibtop < GirFFI::StructBase
19
21
  end
20
22
 
21
23
  it 'can be created using Glibtop.init' do
@@ -1455,8 +1455,7 @@ describe Regress do
1455
1455
 
1456
1456
  describe 'Regress::TestFundamentalObject' do
1457
1457
  it 'does not have GObject::Object as an ancestor' do
1458
- refute_includes Regress::TestFundamentalObject.ancestors,
1459
- GObject::Object
1458
+ refute(Regress::TestFundamentalObject < GObject::Object)
1460
1459
  end
1461
1460
 
1462
1461
  it 'cannot be instantiated' do
@@ -1541,8 +1540,7 @@ describe Regress do
1541
1540
  end
1542
1541
 
1543
1542
  it 'extends InterfaceBase' do
1544
- metaclass = class << Regress::TestInterface; self; end
1545
- assert_includes metaclass.ancestors, GirFFI::InterfaceBase
1543
+ Regress::TestInterface.singleton_class.must_include GirFFI::InterfaceBase
1546
1544
  end
1547
1545
 
1548
1546
  it 'has non-zero positive result for #gtype' do
@@ -3745,6 +3743,7 @@ describe Regress do
3745
3743
  a = u
3746
3744
  end
3747
3745
  assert_equal [244, 2 * 244, 6 + 31], [y, z, q]
3746
+ a.must_be_instance_of Regress::TestCallbackUserData
3748
3747
  end
3749
3748
 
3750
3749
  it 'has a working function #test_uint' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gir_ffi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matijs van Zuijlen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-08 00:00:00.000000000 Z
11
+ date: 2018-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -389,6 +389,7 @@ files:
389
389
  - test/gir_ffi/callback_base_test.rb
390
390
  - test/gir_ffi/class_base_test.rb
391
391
  - test/gir_ffi/core_test.rb
392
+ - test/gir_ffi/enum_base_test.rb
392
393
  - test/gir_ffi/error_type_info_test.rb
393
394
  - test/gir_ffi/ffi_ext/pointer_test.rb
394
395
  - test/gir_ffi/g_type_test.rb