gir_ffi 0.8.6 → 0.9.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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +18 -0
  3. data/README.md +3 -4
  4. data/lib/ffi-glib.rb +1 -0
  5. data/lib/ffi-glib/container_class_methods.rb +12 -0
  6. data/lib/ffi-glib/destroy_notify.rb +15 -0
  7. data/lib/ffi-glib/main_loop.rb +23 -4
  8. data/lib/ffi-gobject.rb +4 -2
  9. data/lib/ffi-gobject/object.rb +31 -16
  10. data/lib/ffi-gobject/object_class.rb +4 -0
  11. data/lib/ffi-gobject/value.rb +3 -3
  12. data/lib/ffi-gobject_introspection/i_flags_info.rb +0 -1
  13. data/lib/gir_ffi-base/gobject/lib.rb +10 -0
  14. data/lib/gir_ffi/arg_helper.rb +1 -22
  15. data/lib/gir_ffi/boxed_base.rb +1 -0
  16. data/lib/gir_ffi/builder.rb +7 -1
  17. data/lib/gir_ffi/builders/argument_builder.rb +21 -9
  18. data/lib/gir_ffi/builders/argument_builder_collection.rb +28 -9
  19. data/lib/gir_ffi/builders/base_argument_builder.rb +36 -12
  20. data/lib/gir_ffi/builders/base_method_builder.rb +1 -1
  21. data/lib/gir_ffi/builders/callback_argument_builder.rb +4 -0
  22. data/lib/gir_ffi/builders/closure_to_pointer_convertor.rb +3 -2
  23. data/lib/gir_ffi/builders/constructor_builder.rb +1 -1
  24. data/lib/gir_ffi/builders/enum_builder.rb +4 -4
  25. data/lib/gir_ffi/builders/error_argument_builder.rb +4 -0
  26. data/lib/gir_ffi/builders/field_builder.rb +23 -9
  27. data/lib/gir_ffi/builders/flags_builder.rb +28 -0
  28. data/lib/gir_ffi/builders/full_c_to_ruby_convertor.rb +18 -0
  29. data/lib/gir_ffi/builders/module_builder.rb +1 -0
  30. data/lib/gir_ffi/builders/null_argument_builder.rb +9 -1
  31. data/lib/gir_ffi/builders/object_builder.rb +7 -4
  32. data/lib/gir_ffi/builders/property_builder.rb +2 -2
  33. data/lib/gir_ffi/builders/return_value_builder.rb +4 -4
  34. data/lib/gir_ffi/builders/struct_builder.rb +10 -2
  35. data/lib/gir_ffi/builders/type_builder.rb +12 -9
  36. data/lib/gir_ffi/builders/unintrospectable_boxed_builder.rb +26 -0
  37. data/lib/gir_ffi/builders/user_defined_builder.rb +2 -2
  38. data/lib/gir_ffi/builders/with_layout.rb +1 -1
  39. data/lib/gir_ffi/callback_base.rb +13 -5
  40. data/lib/gir_ffi/core.rb +1 -0
  41. data/lib/gir_ffi/error_argument_info.rb +4 -0
  42. data/lib/gir_ffi/flags_base.rb +63 -0
  43. data/lib/gir_ffi/in_pointer.rb +1 -3
  44. data/lib/gir_ffi/info_ext/i_type_info.rb +6 -0
  45. data/lib/gir_ffi/object_base.rb +9 -1
  46. data/lib/gir_ffi/object_store.rb +26 -0
  47. data/lib/gir_ffi/unintrospectable_boxed_info.rb +31 -0
  48. data/lib/gir_ffi/unintrospectable_type_info.rb +5 -0
  49. data/lib/gir_ffi/user_defined_type_info.rb +19 -0
  50. data/lib/gir_ffi/version.rb +1 -1
  51. data/test/ffi-glib/destroy_notify_test.rb +13 -0
  52. data/test/ffi-glib/main_loop_test.rb +3 -3
  53. data/test/ffi-gobject/object_class_test.rb +8 -0
  54. data/test/ffi-gobject/object_test.rb +23 -5
  55. data/test/ffi-gobject/value_test.rb +19 -5
  56. data/test/ffi-gobject_test.rb +2 -2
  57. data/test/gir_ffi/builders/argument_builder_test.rb +12 -2
  58. data/test/gir_ffi/builders/constructor_builder_test.rb +4 -4
  59. data/test/gir_ffi/builders/function_builder_test.rb +46 -3
  60. data/test/gir_ffi/builders/object_builder_test.rb +25 -0
  61. data/test/gir_ffi/builders/property_builder_test.rb +4 -4
  62. data/test/gir_ffi/builders/struct_builder_test.rb +15 -13
  63. data/test/gir_ffi/builders/unintrospectable_boxed_builder_test.rb +33 -0
  64. data/test/gir_ffi/builders/unintrospectable_builder_test.rb +6 -0
  65. data/test/gir_ffi/builders/user_defined_builder_test.rb +7 -1
  66. data/test/gir_ffi/callback_base_test.rb +12 -2
  67. data/test/gir_ffi/object_base_test.rb +14 -0
  68. data/test/integration/callback_exceptions_test.rb +61 -0
  69. data/test/integration/generated_gimarshallingtests_test.rb +70 -70
  70. data/test/integration/generated_gio_test.rb +1 -1
  71. data/test/integration/generated_gobject_test.rb +1 -1
  72. data/test/integration/generated_gtop_test.rb +5 -1
  73. data/test/integration/generated_regress_test.rb +83 -102
  74. data/test/integration/generated_warnlib_test.rb +2 -2
  75. metadata +42 -4
@@ -1,14 +1,16 @@
1
1
  module GirFFI
2
2
  module Builders
3
- # Class representing the argument and return value builders for a callback
4
- # mapping function or marshaller. Implements collecting the conversion code
5
- # and parameter and variable names for use by function builders.
3
+ # Class representing the argument and return value builders for a method,
4
+ # callback mapping function or marshaller. Implements collecting the
5
+ # conversion code and parameter and variable names for use by function
6
+ # builders.
6
7
  class ArgumentBuilderCollection
7
8
  attr_reader :return_value_builder
8
9
 
9
- def initialize(return_value_builder, argument_builders, options = {})
10
- @receiver_builder = options[:receiver_builder]
11
- @error_argument_builder = options[:error_argument_builder]
10
+ def initialize(return_value_builder, argument_builders,
11
+ receiver_builder: nil, error_argument_builder: nil)
12
+ @receiver_builder = receiver_builder
13
+ @error_argument_builder = error_argument_builder
12
14
  @base_argument_builders = argument_builders
13
15
  @return_value_builder = return_value_builder
14
16
  set_up_argument_relations
@@ -32,7 +34,21 @@ module GirFFI
32
34
  end
33
35
 
34
36
  def method_argument_names
35
- @method_argument_names ||= argument_builders.map(&:method_argument_name).compact
37
+ @method_argument_names ||=
38
+ begin
39
+ base = []
40
+ block = nil
41
+ argument_builders.each do |it|
42
+ name = it.method_argument_name
43
+ if !block && it.block_argument?
44
+ block = "&#{name}"
45
+ else
46
+ base << name
47
+ end
48
+ end
49
+ base << block if block
50
+ base.compact
51
+ end
36
52
  end
37
53
 
38
54
  def return_value_name
@@ -58,8 +74,11 @@ module GirFFI
58
74
 
59
75
  def set_up_argument_relations
60
76
  @base_argument_builders.each do |bldr|
61
- if (idx = bldr.closure) >= 0
62
- @base_argument_builders[idx].closure = true
77
+ if (idx = bldr.closure_idx) >= 0
78
+ @base_argument_builders[idx].closure = bldr
79
+ end
80
+ if (idx = bldr.destroy_idx) >= 0
81
+ @base_argument_builders[idx].mark_as_destroy_notifier bldr
63
82
  end
64
83
  end
65
84
  all_builders.each do |bldr|
@@ -15,23 +15,13 @@ module GirFFI
15
15
  attr_reader :arginfo
16
16
  attr_accessor :length_arg, :array_arg
17
17
 
18
- # TODO: closure unfortunately means two things in GLib: a closure
19
- # argument (user_data), and the Closure class (a callable object). Make
20
- # the distinction more explicit in GirFFI.
21
- def closure?
22
- @is_closure
23
- end
24
-
25
- def closure=(arg)
26
- @is_closure = arg
27
- end
28
-
29
18
  def initialize(var_gen, arginfo)
30
19
  @var_gen = var_gen
31
20
  @arginfo = arginfo
32
21
  @length_arg = nil
33
22
  @array_arg = nil
34
23
  @is_closure = false
24
+ @destroy_notifier = false
35
25
  end
36
26
 
37
27
  def name
@@ -60,10 +50,44 @@ module GirFFI
60
50
  type_info.array_length
61
51
  end
62
52
 
63
- def closure
53
+ def closure_idx
64
54
  arginfo.closure
65
55
  end
66
56
 
57
+ def destroy_idx
58
+ arginfo.destroy
59
+ end
60
+
61
+ # TODO: closure unfortunately means two things in GLib: a closure
62
+ # argument (user_data), and the Closure class (a callable object). Make
63
+ # the distinction more explicit in GirFFI.
64
+ def closure=(arg)
65
+ @is_closure = arg
66
+ end
67
+
68
+ # TODO: Unify relationship set-up methods and improve naming. We
69
+ # currently have length_arg=, array_arg=, closure= and
70
+ # mark_as_destroy_notifier.
71
+ def mark_as_destroy_notifier(callback)
72
+ @destroy_notifier = callback
73
+ end
74
+
75
+ def array_length_parameter?
76
+ @array_arg
77
+ end
78
+
79
+ def closure?
80
+ @is_closure
81
+ end
82
+
83
+ def destroy_notifier?
84
+ @destroy_notifier
85
+ end
86
+
87
+ def helper_argument?
88
+ array_length_parameter? || closure? || destroy_notifier?
89
+ end
90
+
67
91
  def ownership_transfer
68
92
  arginfo.ownership_transfer
69
93
  end
@@ -53,7 +53,7 @@ module GirFFI
53
53
  # Methods used by MethodTemplate
54
54
 
55
55
  def invocation
56
- "#{lib_name}.#{@info.symbol} #{function_call_arguments.join(', ')}"
56
+ "#{lib_name}.#{@info.symbol} #{function_call_arguments.join(', ')}".strip
57
57
  end
58
58
 
59
59
  def method_arguments
@@ -12,6 +12,10 @@ module GirFFI
12
12
  @method_argument_name ||= name || new_variable
13
13
  end
14
14
 
15
+ def block_argument?
16
+ false
17
+ end
18
+
15
19
  def pre_converted_name
16
20
  @pre_converted_name ||= new_variable
17
21
  end
@@ -3,12 +3,13 @@ module GirFFI
3
3
  # Builder that generates code to convert closure arguments ('user data')
4
4
  # from Ruby to C. Used by argument builders.
5
5
  class ClosureToPointerConvertor
6
- def initialize(argument_name)
6
+ def initialize(argument_name, callback_argument)
7
7
  @argument_name = argument_name
8
+ @callback_argument = callback_argument
8
9
  end
9
10
 
10
11
  def conversion
11
- "GirFFI::InPointer.from_closure_data(#{@argument_name})"
12
+ "GirFFI::InPointer.from_closure_data(#{@callback_argument.call_argument_name}.object_id)"
12
13
  end
13
14
  end
14
15
  end
@@ -27,7 +27,7 @@ module GirFFI
27
27
  end
28
28
 
29
29
  def method_arguments
30
- ['*args']
30
+ ['*args', '&block']
31
31
  end
32
32
 
33
33
  def preparation
@@ -21,7 +21,7 @@ module GirFFI
21
21
  end
22
22
 
23
23
  def setup_class
24
- setup_ffi_enum
24
+ setup_ffi_type
25
25
  klass.extend superclass
26
26
  setup_constants
27
27
  stub_methods
@@ -32,8 +32,8 @@ module GirFFI
32
32
  @klass ||= get_or_define_module namespace_module, @classname
33
33
  end
34
34
 
35
- def setup_ffi_enum
36
- @enum = optionally_define_constant klass, :Enum do
35
+ def setup_ffi_type
36
+ optionally_define_constant klass, :Enum do
37
37
  lib.enum(enum_sym, value_spec)
38
38
  end
39
39
  end
@@ -51,7 +51,7 @@ module GirFFI
51
51
  end
52
52
 
53
53
  def superclass
54
- @superclass ||= EnumBase
54
+ EnumBase
55
55
  end
56
56
  end
57
57
  end
@@ -10,6 +10,10 @@ module GirFFI
10
10
  nil
11
11
  end
12
12
 
13
+ def block_argument?
14
+ false
15
+ end
16
+
13
17
  def return_value_name
14
18
  nil
15
19
  end
@@ -9,10 +9,12 @@ module GirFFI
9
9
  # Convertor for fields for field getters. Used when building getter
10
10
  # methods.
11
11
  class GetterArgumentBuilder < BaseArgumentBuilder
12
- def initialize(var_gen, field_argument_info, field_info, options = {})
12
+ def initialize(var_gen, field_argument_info, field_info,
13
+ array_length_idx: -1)
13
14
  super(var_gen, field_argument_info)
14
15
  @field_info = field_info
15
- @length_arg = options.fetch(:length_argument) { NullArgumentBuilder.new }
16
+ @length_arg = NullArgumentBuilder.new
17
+ @array_length_idx = array_length_idx
16
18
  end
17
19
 
18
20
  def pre_conversion
@@ -47,6 +49,10 @@ module GirFFI
47
49
  end
48
50
  end
49
51
 
52
+ def array_length_idx
53
+ @array_length_idx
54
+ end
55
+
50
56
  private
51
57
 
52
58
  def field_offset
@@ -98,6 +104,10 @@ module GirFFI
98
104
  -1
99
105
  end
100
106
 
107
+ def destroy
108
+ -1
109
+ end
110
+
101
111
  def direction
102
112
  :out
103
113
  end
@@ -163,22 +173,26 @@ module GirFFI
163
173
  @argument_builders ||=
164
174
  ArgumentBuilderCollection.new(
165
175
  NullReturnValueBuilder.new,
166
- [getter_argument_builder, length_argument_builder])
176
+ base_argument_builders)
177
+ end
178
+
179
+ def base_argument_builders
180
+ if array_length_field
181
+ [getter_argument_builder, length_argument_builder]
182
+ else
183
+ [getter_argument_builder]
184
+ end
167
185
  end
168
186
 
169
187
  def getter_argument_builder
170
188
  @getter_argument_builder ||=
171
189
  GetterArgumentBuilder.new(var_gen, field_argument_info, @info,
172
- length_argument: length_argument_builder)
190
+ array_length_idx: array_length_field ? 1 : -1)
173
191
  end
174
192
 
175
193
  def length_argument_builder
176
194
  @length_argument_builder ||=
177
- if array_length_field
178
- GetterArgumentBuilder.new(var_gen, length_argument_info, array_length_field)
179
- else
180
- NullArgumentBuilder.new
181
- end
195
+ GetterArgumentBuilder.new(var_gen, length_argument_info, array_length_field)
182
196
  end
183
197
 
184
198
  def array_length_field
@@ -0,0 +1,28 @@
1
+ require 'gir_ffi/builders/enum_builder'
2
+ require 'gir_ffi/flags_base'
3
+
4
+ module GirFFI
5
+ module Builders
6
+ # Implements the creation of a flags type. The type will be
7
+ # attached to the appropriate namespace module, and will be defined
8
+ # as a bit_mask for FFI.
9
+ class FlagsBuilder < EnumBuilder
10
+ def setup_ffi_type
11
+ optionally_define_constant klass, :BitMask do
12
+ lib.bit_mask(enum_sym, value_spec)
13
+ end
14
+ end
15
+
16
+ def value_spec
17
+ info.values.map do|vinfo|
18
+ val = GirFFI::ArgHelper.cast_uint32_to_int32(vinfo.value)
19
+ { vinfo.name.to_sym => val }
20
+ end.reduce(:merge)
21
+ end
22
+
23
+ def superclass
24
+ FlagsBase
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ require 'gir_ffi/builders/c_to_ruby_convertor'
2
+
3
+ module GirFFI
4
+ module Builders
5
+ # Builder that generates code to convert values from C to Ruby, including
6
+ # GValue unpacking. Used by argument builders.
7
+ class FullCToRubyConvertor < CToRubyConvertor
8
+ def conversion
9
+ base = super
10
+ if @type_info.gvalue?
11
+ "#{base}.get_value"
12
+ else
13
+ base
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -83,6 +83,7 @@ module GirFFI
83
83
 
84
84
  def setup_lib_for_ffi
85
85
  lib.extend FFI::Library
86
+ lib.extend FFI::BitMasks
86
87
  lib.ffi_lib_flags :global, :lazy
87
88
  if shared_library_specification
88
89
  lib.ffi_lib(*shared_library_specification.split(/,/))
@@ -32,10 +32,18 @@ module GirFFI
32
32
  nil
33
33
  end
34
34
 
35
- def closure
35
+ def closure_idx
36
36
  -1
37
37
  end
38
38
 
39
+ def destroy_idx
40
+ -1
41
+ end
42
+
43
+ def block_argument?
44
+ false
45
+ end
46
+
39
47
  def post_converted_name
40
48
  nil
41
49
  end
@@ -38,6 +38,13 @@ module GirFFI
38
38
  @ancestor_infos ||= [info] + info.interfaces + parent_ancestor_infos
39
39
  end
40
40
 
41
+ protected
42
+
43
+ def object_class_struct_info
44
+ @object_class_struct_info ||=
45
+ info.class_struct || parent_builder.object_class_struct_info
46
+ end
47
+
41
48
  private
42
49
 
43
50
  def setup_class
@@ -131,10 +138,6 @@ module GirFFI
131
138
  end
132
139
  end
133
140
 
134
- def object_class_struct_info
135
- @object_class_struct_info ||= info.class_struct
136
- end
137
-
138
141
  def seek_in_ancestor_infos
139
142
  ancestor_infos.each do |info|
140
143
  item = yield info
@@ -50,7 +50,7 @@ module GirFFI
50
50
  capture = getter_builder.capture_variable_name
51
51
  <<-CODE.reset_indentation
52
52
  def #{getter_name}
53
- #{capture} = get_property("#{property_name}").get_value_plain
53
+ #{capture} = get_property("#{property_name}")
54
54
  #{getter_builder.post_conversion.join("\n")}
55
55
  #{getter_builder.return_value_name}
56
56
  end
@@ -60,7 +60,7 @@ module GirFFI
60
60
  def simple_getter_def
61
61
  <<-CODE.reset_indentation
62
62
  def #{getter_name}
63
- get_property("#{property_name}").get_value
63
+ get_property("#{property_name}")
64
64
  end
65
65
  CODE
66
66
  end
@@ -1,5 +1,5 @@
1
1
  require 'gir_ffi/builders/base_argument_builder'
2
- require 'gir_ffi/builders/c_to_ruby_convertor'
2
+ require 'gir_ffi/builders/full_c_to_ruby_convertor'
3
3
  require 'gir_ffi/builders/closure_convertor'
4
4
 
5
5
  module GirFFI
@@ -44,9 +44,9 @@ module GirFFI
44
44
  @post_convertor ||= if closure?
45
45
  ClosureConvertor.new(capture_variable_name)
46
46
  else
47
- CToRubyConvertor.new(type_info,
48
- capture_variable_name,
49
- length_argument_name)
47
+ FullCToRubyConvertor.new(type_info,
48
+ capture_variable_name,
49
+ length_argument_name)
50
50
  end
51
51
  end
52
52
 
@@ -9,9 +9,17 @@ module GirFFI
9
9
  FFI::Struct
10
10
  end
11
11
 
12
- private
13
-
14
12
  def superclass
13
+ if info.gtype_struct?
14
+ # HACK: Inheritance chain is not expressed in GObject's code correctly.
15
+ if info.full_type_name == 'GObject::InitiallyUnownedClass'
16
+ return GObject::ObjectClass
17
+ else
18
+ type = fields.first.field_type
19
+ return type.tag_or_class if type.tag == :interface
20
+ end
21
+ end
22
+
15
23
  StructBase
16
24
  end
17
25
  end