gir_ffi 0.9.5 → 0.10.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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