gir_ffi 0.9.5 → 0.10.0.pre1

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +9 -0
  3. data/lib/ffi-glib/byte_array.rb +1 -1
  4. data/lib/ffi-glib/bytes.rb +4 -4
  5. data/lib/ffi-glib/container_class_methods.rb +2 -0
  6. data/lib/ffi-glib/iconv.rb +2 -2
  7. data/lib/ffi-glib/variant.rb +10 -2
  8. data/lib/ffi-gobject.rb +6 -14
  9. data/lib/ffi-gobject/object.rb +7 -0
  10. data/lib/ffi-gobject/object_class.rb +1 -1
  11. data/lib/ffi-gobject/param_spec.rb +12 -0
  12. data/lib/ffi-gobject/value.rb +20 -11
  13. data/lib/gir_ffi-base/gobject.rb +35 -3
  14. data/lib/gir_ffi-base/gobject/lib.rb +2 -0
  15. data/lib/gir_ffi/allocation_helper.rb +11 -0
  16. data/lib/gir_ffi/arg_helper.rb +4 -0
  17. data/lib/gir_ffi/boxed_base.rb +28 -32
  18. data/lib/gir_ffi/builders/argument_builder.rb +31 -6
  19. data/lib/gir_ffi/builders/c_to_ruby_convertor.rb +36 -7
  20. data/lib/gir_ffi/builders/callback_argument_builder.rb +24 -10
  21. data/lib/gir_ffi/builders/closure_to_pointer_convertor.rb +1 -1
  22. data/lib/gir_ffi/builders/field_builder.rb +28 -10
  23. data/lib/gir_ffi/builders/full_c_to_ruby_convertor.rb +2 -3
  24. data/lib/gir_ffi/builders/initializer_return_value_builder.rb +5 -1
  25. data/lib/gir_ffi/builders/null_argument_builder.rb +0 -12
  26. data/lib/gir_ffi/builders/pointer_value_convertor.rb +38 -0
  27. data/lib/gir_ffi/builders/return_value_builder.rb +12 -10
  28. data/lib/gir_ffi/builders/ruby_to_c_convertor.rb +21 -2
  29. data/lib/gir_ffi/builders/struct_builder.rb +9 -2
  30. data/lib/gir_ffi/builders/{boxed_builder.rb → struct_like.rb} +2 -5
  31. data/lib/gir_ffi/builders/unintrospectable_boxed_builder.rb +5 -2
  32. data/lib/gir_ffi/builders/union_builder.rb +5 -2
  33. data/lib/gir_ffi/enum_base.rb +4 -0
  34. data/lib/gir_ffi/error_argument_info.rb +0 -16
  35. data/lib/gir_ffi/ffi_ext/pointer.rb +11 -5
  36. data/lib/gir_ffi/flags_base.rb +4 -0
  37. data/lib/gir_ffi/in_out_pointer.rb +5 -30
  38. data/lib/gir_ffi/in_pointer.rb +5 -4
  39. data/lib/gir_ffi/info_ext/i_type_info.rb +3 -5
  40. data/lib/gir_ffi/object_base.rb +4 -0
  41. data/lib/gir_ffi/sized_array.rb +20 -0
  42. data/lib/gir_ffi/struct_base.rb +13 -2
  43. data/lib/gir_ffi/struct_like_base.rb +53 -0
  44. data/lib/gir_ffi/union_base.rb +7 -1
  45. data/lib/gir_ffi/version.rb +1 -1
  46. data/test/ffi-glib/destroy_notify_test.rb +4 -1
  47. data/test/ffi-gobject/param_spec_test.rb +18 -0
  48. data/test/gir_ffi/arg_helper_test.rb +17 -0
  49. data/test/gir_ffi/boxed_base_test.rb +24 -0
  50. data/test/gir_ffi/builders/argument_builder_test.rb +156 -63
  51. data/test/gir_ffi/builders/callback_argument_builder_test.rb +10 -10
  52. data/test/gir_ffi/builders/callback_builder_test.rb +31 -8
  53. data/test/gir_ffi/builders/field_builder_test.rb +32 -30
  54. data/test/gir_ffi/builders/function_builder_test.rb +251 -45
  55. data/test/gir_ffi/builders/initializer_builder_test.rb +17 -1
  56. data/test/gir_ffi/builders/return_value_builder_test.rb +115 -68
  57. data/test/gir_ffi/builders/struct_builder_test.rb +6 -0
  58. data/test/gir_ffi/builders/unintrospectable_builder_test.rb +4 -1
  59. data/test/gir_ffi/builders/vfunc_builder_test.rb +10 -10
  60. data/test/gir_ffi/in_out_pointer_test.rb +12 -81
  61. data/test/gir_ffi/in_pointer_test.rb +0 -17
  62. data/test/gir_ffi/info_ext/i_type_info_test.rb +0 -10
  63. data/test/gir_ffi/sized_array_test.rb +62 -0
  64. data/test/gir_ffi/struct_base_test.rb +24 -0
  65. data/test/gir_ffi/union_base_test.rb +24 -0
  66. data/test/gir_ffi/version_test.rb +1 -1
  67. data/test/integration/generated_gimarshallingtests_test.rb +32 -12
  68. data/test/integration/generated_regress_test.rb +9 -12
  69. metadata +12 -8
  70. data/lib/ffi-gobject/base.rb +0 -27
  71. data/lib/gir_ffi/user_data_argument_info.rb +0 -24
  72. data/lib/gir_ffi/user_data_type_info.rb +0 -22
@@ -4,32 +4,57 @@ module GirFFI
4
4
  # Builder that generates code to convert values from C to Ruby. Used by
5
5
  # argument builders.
6
6
  class CToRubyConvertor
7
- def initialize(type_info, argument_name, length_arg)
7
+ def initialize(type_info, argument, length_arg, ownership_transfer: nil)
8
8
  @type_info = type_info
9
- @argument_name = argument_name
9
+ @argument = argument
10
10
  @length_arg = length_arg
11
+ @ownership_transfer = ownership_transfer
11
12
  end
12
13
 
13
14
  def conversion
14
15
  case @type_info.flattened_tag
15
16
  when :utf8, :filename
16
- "#{@argument_name}.to_utf8"
17
+ if @ownership_transfer == :everything
18
+ "#{@argument}.tap { |it| it.autorelease = true }.to_utf8"
19
+ else
20
+ "#{@argument}.to_utf8"
21
+ end
22
+ when :object
23
+ base = "#{@type_info.argument_class_name}.wrap(#{conversion_argument_list})"
24
+ @ownership_transfer == :nothing ? "#{base}.tap { |it| it && it.ref }" : base
17
25
  else
18
- "#{@type_info.argument_class_name}.wrap(#{conversion_argument_list})"
26
+ "#{argument_class}.#{conversion_method}(#{conversion_argument_list})"
19
27
  end
20
28
  end
21
29
 
22
30
  private
23
31
 
32
+ def conversion_method
33
+ case @type_info.flattened_tag
34
+ when :struct, :union
35
+ case @ownership_transfer
36
+ when :everything
37
+ 'wrap_own'
38
+ when :nothing
39
+ 'wrap_copy'
40
+ else
41
+ 'wrap'
42
+ end
43
+ else
44
+ 'wrap'
45
+ end
46
+ end
47
+
24
48
  def conversion_argument_list
25
49
  conversion_arguments.join(', ')
26
50
  end
27
51
 
28
52
  def conversion_arguments
29
- if @type_info.flattened_tag == :c
30
- [@type_info.element_type.inspect, array_size, @argument_name]
53
+ case @type_info.flattened_tag
54
+ when :c
55
+ [@type_info.element_type.inspect, array_size, @argument]
31
56
  else
32
- @type_info.extra_conversion_arguments.map(&:inspect).push(@argument_name)
57
+ @type_info.extra_conversion_arguments.map(&:inspect).push(@argument)
33
58
  end
34
59
  end
35
60
 
@@ -40,6 +65,10 @@ module GirFFI
40
65
  @type_info.array_fixed_size
41
66
  end
42
67
  end
68
+
69
+ def argument_class
70
+ @type_info.argument_class_name
71
+ end
43
72
  end
44
73
  end
45
74
  end
@@ -3,6 +3,7 @@ require 'gir_ffi/builders/base_argument_builder'
3
3
  require 'gir_ffi/builders/c_to_ruby_convertor'
4
4
  require 'gir_ffi/builders/closure_convertor'
5
5
  require 'gir_ffi/builders/null_convertor'
6
+ require 'gir_ffi/builders/pointer_value_convertor'
6
7
 
7
8
  module GirFFI
8
9
  module Builders
@@ -62,11 +63,11 @@ module GirFFI
62
63
  def post_conversion
63
64
  case direction
64
65
  when :out, :inout
65
- [outgoing_post_conversion]
66
+ [value_to_pointer_conversion]
66
67
  when :error
67
68
  [
68
69
  "rescue => #{result_name}",
69
- outgoing_post_conversion,
70
+ value_to_pointer_conversion,
70
71
  'end'
71
72
  ]
72
73
  else
@@ -82,12 +83,25 @@ module GirFFI
82
83
 
83
84
  def pre_convertor_argument
84
85
  if direction == :inout
85
- "#{out_parameter_name}.to_value"
86
+ pointer_to_value_conversion
86
87
  else
87
88
  method_argument_name
88
89
  end
89
90
  end
90
91
 
92
+ def pointer_value_convertor
93
+ @pointer_value_convertor ||= PointerValueConvertor.new(type_spec)
94
+ end
95
+
96
+ def pointer_to_value_conversion
97
+ pointer_value_convertor.pointer_to_value(out_parameter_name)
98
+ end
99
+
100
+ def value_to_pointer_conversion
101
+ pointer_value_convertor.value_to_pointer(out_parameter_name,
102
+ post_convertor.conversion)
103
+ end
104
+
91
105
  def pre_convertor
92
106
  @pre_convertor ||= if closure?
93
107
  ClosureConvertor.new(pre_convertor_argument)
@@ -108,10 +122,6 @@ module GirFFI
108
122
  "#{pre_converted_name} = #{pre_convertor.conversion}"
109
123
  end
110
124
 
111
- def outgoing_post_conversion
112
- "#{out_parameter_name}.set_value #{post_convertor.conversion}"
113
- end
114
-
115
125
  def post_convertor
116
126
  @post_convertor ||= if type_info.needs_ruby_to_c_conversion_for_callbacks?
117
127
  RubyToCConvertor.new(type_info, post_convertor_argument)
@@ -129,16 +139,20 @@ module GirFFI
129
139
  end
130
140
 
131
141
  def out_parameter_preparation
132
- type_spec = type_info.tag_or_class
133
142
  value = if allocated_by_us?
134
- "GirFFI::InOutPointer.new(#{type_spec[1].inspect})" \
143
+ ffi_type = TypeMap.type_specification_to_ffi_type type_spec[1]
144
+ "GirFFI::AllocationHelper.allocate(#{ffi_type.inspect})" \
135
145
  ".tap { |ptr| #{method_argument_name}.put_pointer 0, ptr }"
136
146
  else
137
- "GirFFI::InOutPointer.new(#{type_spec.inspect}, #{method_argument_name})"
147
+ method_argument_name
138
148
  end
139
149
  "#{out_parameter_name} = #{value}"
140
150
  end
141
151
 
152
+ def type_spec
153
+ type_info.tag_or_class
154
+ end
155
+
142
156
  # Check if an out argument needs to be allocated by us, the callee. Since
143
157
  # caller_allocates is false by default, we must also check that the type
144
158
  # is a pointer. For example, an out parameter of type gint8* will always
@@ -10,7 +10,7 @@ module GirFFI
10
10
  end
11
11
 
12
12
  def conversion
13
- "GirFFI::InPointer.from_closure_data(#{callback_argument_name})"
13
+ "GirFFI::ArgHelper.store(#{callback_argument_name})"
14
14
  end
15
15
 
16
16
  private
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  require 'gir_ffi/builders/argument_builder'
3
+ require 'gir_ffi/builders/base_argument_builder'
4
+ require 'gir_ffi/builders/null_argument_builder'
5
+ require 'gir_ffi/builders/pointer_value_convertor'
3
6
  require 'gir_ffi/variable_name_generator'
4
7
  require 'gir_ffi/field_argument_info'
5
8
 
@@ -23,8 +26,7 @@ module GirFFI
23
26
  def pre_conversion
24
27
  [
25
28
  "#{field_ptr} = @struct.to_ptr + #{field_offset}",
26
- "#{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag}, #{field_ptr})",
27
- "#{bare_value} = #{typed_ptr}.to_value"
29
+ "#{bare_value} = #{pointer_to_value_conversion}"
28
30
  ]
29
31
  end
30
32
 
@@ -54,6 +56,10 @@ module GirFFI
54
56
 
55
57
  private
56
58
 
59
+ def pointer_to_value_conversion
60
+ PointerValueConvertor.new(field_type_tag).pointer_to_value(field_ptr)
61
+ end
62
+
57
63
  def field_offset
58
64
  @field_info.offset
59
65
  end
@@ -71,7 +77,7 @@ module GirFFI
71
77
  end
72
78
 
73
79
  def field_type_tag
74
- @field_type_tag ||= @field_info.field_type.tag_or_class.inspect
80
+ @field_type_tag ||= @field_info.field_type.tag_or_class
75
81
  end
76
82
 
77
83
  def field_type
@@ -112,7 +118,7 @@ module GirFFI
112
118
  end
113
119
 
114
120
  def ownership_transfer
115
- :everything
121
+ :nothing
116
122
  end
117
123
 
118
124
  def caller_allocates?
@@ -233,7 +239,9 @@ module GirFFI
233
239
  end
234
240
 
235
241
  def setup_getter
236
- container_class.class_eval getter_def unless container_defines_getter_method?
242
+ return if container_defines_getter_method?
243
+ return if hidden_struct_type?
244
+ container_class.class_eval getter_def
237
245
  end
238
246
 
239
247
  def container_defines_getter_method?
@@ -241,7 +249,9 @@ module GirFFI
241
249
  end
242
250
 
243
251
  def setup_setter
244
- container_class.class_eval setter_def if info.writable?
252
+ return unless info.writable?
253
+ return if hidden_struct_type?
254
+ container_class.class_eval setter_def
245
255
  end
246
256
 
247
257
  def getter_def
@@ -254,22 +264,25 @@ module GirFFI
254
264
  builder = setter_builder
255
265
 
256
266
  field_ptr = builder.new_variable
257
- typed_ptr = builder.new_variable
258
267
 
259
268
  <<-CODE.reset_indentation
260
269
  def #{info.name}= #{builder.method_argument_name}
261
270
  #{field_ptr} = @struct.to_ptr + #{info.offset}
262
- #{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag}, #{field_ptr})
263
271
  #{builder.pre_conversion.join("\n ")}
264
- #{typed_ptr}.set_value #{builder.call_argument_name}
272
+ #{value_storage(field_ptr, builder)}
265
273
  end
266
274
  CODE
267
275
  end
268
276
 
269
277
  private
270
278
 
279
+ def value_storage(typed_ptr, builder)
280
+ PointerValueConvertor.new(field_type_tag).
281
+ value_to_pointer(typed_ptr, builder.call_argument_name)
282
+ end
283
+
271
284
  def field_type_tag
272
- @field_type_tag ||= info.field_type.tag_or_class.inspect
285
+ @field_type_tag ||= field_type.tag_or_class
273
286
  end
274
287
 
275
288
  def container_class
@@ -296,6 +309,11 @@ module GirFFI
296
309
  @setter_builder ||= ArgumentBuilder.new(VariableNameGenerator.new,
297
310
  field_argument_info)
298
311
  end
312
+
313
+ # rubocop:disable Style/ZeroLengthPredicate
314
+ def hidden_struct_type?
315
+ field_type.flattened_tag == :struct && field_type.interface.size == 0
316
+ end
299
317
  end
300
318
  end
301
319
  end
@@ -7,11 +7,10 @@ module GirFFI
7
7
  # GValue unpacking. Used by argument builders.
8
8
  class FullCToRubyConvertor < CToRubyConvertor
9
9
  def conversion
10
- base = super
11
10
  if @type_info.gvalue?
12
- "#{base}.get_value"
11
+ "GObject::Value.wrap(#{@argument}).get_value"
13
12
  else
14
- base
13
+ super
15
14
  end
16
15
  end
17
16
  end
@@ -6,7 +6,11 @@ module GirFFI
6
6
  # Implements post-conversion for initializer functions
7
7
  class InitializerReturnValueBuilder < BaseReturnValueBuilder
8
8
  def post_conversion
9
- ["store_pointer(#{capture_variable_name})"]
9
+ result = []
10
+ if specialized_type_tag == :struct
11
+ result << "#{capture_variable_name}.autorelease = true"
12
+ end
13
+ result << "store_pointer(#{capture_variable_name})"
10
14
  end
11
15
  end
12
16
  end
@@ -33,18 +33,6 @@ module GirFFI
33
33
  nil
34
34
  end
35
35
 
36
- def closure_idx
37
- -1
38
- end
39
-
40
- def destroy_idx
41
- -1
42
- end
43
-
44
- def block_argument?
45
- false
46
- end
47
-
48
36
  def post_converted_name
49
37
  nil
50
38
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+ module GirFFI
3
+ module Builders
4
+ # Encapsulates knowledge about how to store values in pointers, and how to
5
+ # fetch values from pointers.
6
+ class PointerValueConvertor
7
+ def initialize(type_spec)
8
+ @type_spec = type_spec
9
+ end
10
+
11
+ def pointer_to_value(ptr_exp)
12
+ case ffi_type_spec
13
+ when Module
14
+ "#{ffi_type_spec}.get_value_from_pointer(#{ptr_exp}, 0)"
15
+ when Symbol
16
+ "#{ptr_exp}.get_#{ffi_type_spec}(0)"
17
+ end
18
+ end
19
+
20
+ def value_to_pointer(ptr_exp, value_exp)
21
+ case ffi_type_spec
22
+ when Module
23
+ "#{ffi_type_spec}.copy_value_to_pointer(#{value_exp}, #{ptr_exp})"
24
+ when Symbol
25
+ "#{ptr_exp}.put_#{ffi_type_spec} 0, #{value_exp}"
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :type_spec
32
+
33
+ def ffi_type_spec
34
+ TypeMap.type_specification_to_ffi_type type_spec
35
+ end
36
+ end
37
+ end
38
+ end
@@ -8,11 +8,11 @@ module GirFFI
8
8
  # Implements building post-processing statements for return values.
9
9
  class ReturnValueBuilder < BaseReturnValueBuilder
10
10
  def post_conversion
11
+ result = []
11
12
  if has_post_conversion?
12
- ["#{post_converted_name} = #{post_convertor.conversion}"]
13
- else
14
- []
13
+ result << "#{post_converted_name} = #{post_convertor.conversion}"
15
14
  end
15
+ result
16
16
  end
17
17
 
18
18
  def has_post_conversion?
@@ -26,13 +26,15 @@ module GirFFI
26
26
  private
27
27
 
28
28
  def post_convertor
29
- @post_convertor ||= if closure?
30
- ClosureConvertor.new(capture_variable_name)
31
- else
32
- FullCToRubyConvertor.new(type_info,
33
- capture_variable_name,
34
- length_argument_name)
35
- end
29
+ @post_convertor ||=
30
+ if closure?
31
+ ClosureConvertor.new(capture_variable_name)
32
+ else
33
+ FullCToRubyConvertor.new(type_info,
34
+ capture_variable_name,
35
+ length_argument_name,
36
+ ownership_transfer: arginfo.ownership_transfer)
37
+ end
36
38
  end
37
39
 
38
40
  def length_argument_name
@@ -4,19 +4,38 @@ module GirFFI
4
4
  # Builder that generates code to convert values from Ruby to C. Used by
5
5
  # argument builders.
6
6
  class RubyToCConvertor
7
- def initialize(type_info, argument_name)
7
+ def initialize(type_info, argument_name, ownership_transfer: nil)
8
8
  @type_info = type_info
9
9
  @argument_name = argument_name
10
+ @ownership_transfer = ownership_transfer
10
11
  end
11
12
 
12
13
  def conversion
13
14
  args = conversion_arguments @argument_name
14
- "#{@type_info.argument_class_name}.from(#{args})"
15
+ "#{@type_info.argument_class_name}.#{conversion_method}(#{args})"
15
16
  end
16
17
 
17
18
  def conversion_arguments(name)
18
19
  @type_info.extra_conversion_arguments.map(&:inspect).push(name).join(', ')
19
20
  end
21
+
22
+ private
23
+
24
+ def conversion_method
25
+ case @type_info.flattened_tag
26
+ when :utf8
27
+ 'from_utf8'
28
+ when :struct, :c
29
+ case @ownership_transfer
30
+ when :everything
31
+ 'copy_from'
32
+ else
33
+ 'from'
34
+ end
35
+ else
36
+ 'from'
37
+ end
38
+ end
20
39
  end
21
40
  end
22
41
  end
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
- require 'gir_ffi/builders/boxed_builder'
2
+ require 'gir_ffi/builders/registered_type_builder'
3
+ require 'gir_ffi/builders/struct_like'
3
4
  require 'gir_ffi/struct_base'
4
5
 
5
6
  module GirFFI
6
7
  module Builders
7
8
  # Implements the creation of a class representing a Struct.
8
- class StructBuilder < BoxedBuilder
9
+ class StructBuilder < RegisteredTypeBuilder
10
+ include StructLike
11
+
9
12
  def layout_superclass
10
13
  FFI::Struct
11
14
  end
@@ -21,6 +24,10 @@ module GirFFI
21
24
  end
22
25
  end
23
26
 
27
+ if GObject.type_fundamental(info.gtype) == GObject::TYPE_BOXED
28
+ return BoxedBase
29
+ end
30
+
24
31
  StructBase
25
32
  end
26
33
  end