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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 16ecb2c35535aff890ce4f63d90d9522a697c042
4
- data.tar.gz: 54025535f0adadd1b3a1bc940d78ec7acbbdf47b
3
+ metadata.gz: 35f0c0d049d4d368c306162a75fbc3e2f5d15f7a
4
+ data.tar.gz: 2bc5789912987309b031c94477290b4988e26f4d
5
5
  SHA512:
6
- metadata.gz: ae487826ba3c2f6e22ae78717b0f9523eb7d06e57a1892d52e50a950a925ae6cf18477bbf147c730b70e50b6c19373332f9b8409b0414a338e543ff3f7c7eea0
7
- data.tar.gz: 16d9cf79dc31a6d5b591e4b835c1f3649414e9179a45e393c869bc8c5750b32573938b4817638b8d0355700a617951f828c3f11c435d1c7797aa0e63780dd9fc
6
+ metadata.gz: cfe43dd9795cc18eb70b096306a7bb7413d581b7df91fbcbe0339788a379f73c4357b5d997db6064fd907563ae23f8943df3cf2b16153de10e3d7f0761f51427
7
+ data.tar.gz: 667648adf9dc0ccfb8371af90fce175c4d28d3c450f2500a7b7715a05c07431d878a508ff4362a77307697554cabccb9f9051462ac840e9b8c8b91c57c633fe1
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.0.pre1 / 2016-03-22
4
+
5
+ * Rework generated method code to use less indirection.
6
+ * Remove unused classes and methods
7
+ * Clearly distinguish boxed types from other structs
8
+ * Take ownership transfer into account in generated methods
9
+ * Properly free unions, structs and boxed types owned by gir_ffi
10
+ * Block access to fields that have disguised types
11
+
3
12
  ## 0.9.5 / 2016-03-05
4
13
 
5
14
  * Abort if modules were defined earlier, e.g., through the gems from the ruby-gnome family.
@@ -9,7 +9,7 @@ module GLib
9
9
  end
10
10
 
11
11
  def append(data)
12
- bytes = GirFFI::InPointer.from :utf8, data
12
+ bytes = GirFFI::InPointer.from_utf8 data
13
13
  len = data.bytesize
14
14
  self.class.wrap Lib.g_byte_array_append(to_ptr, bytes, len)
15
15
  end
@@ -9,12 +9,12 @@ module GLib
9
9
  remove_method :get_data if method_defined? :get_data
10
10
 
11
11
  # @override
12
+ # NOTE: Needed due to mis-identification of the element-type of the
13
+ # resulting sized array for the default binding.
12
14
  def get_data
13
- length_ptr = GirFFI::InOutPointer.for :gsize
15
+ length_ptr = FFI::MemoryPointer.new :size_t
14
16
  data_ptr = Lib.g_bytes_get_data self, length_ptr
15
- length = length_ptr.to_value
16
- # NOTE: Needed due to mis-identification of the element-type of the
17
- # resulting sized array for the default binding.
17
+ length = length_ptr.get_size_t(0)
18
18
  GirFFI::SizedArray.wrap(:guint8, length, data_ptr)
19
19
  end
20
20
 
@@ -10,6 +10,8 @@ module GLib
10
10
  nil
11
11
  when FFI::Pointer
12
12
  ptr
13
+ when self
14
+ ptr.to_ptr
13
15
  when GirFFI::BoxedBase
14
16
  ptr.to_ptr
15
17
  end
@@ -5,8 +5,8 @@ module GLib
5
5
  # Overrides for IConv
6
6
  class IConv
7
7
  def self.open(to_codeset, from_codeset)
8
- to_ptr = GirFFI::InPointer.from(:utf8, to_codeset)
9
- from_ptr = GirFFI::InPointer.from(:utf8, from_codeset)
8
+ to_ptr = GirFFI::InPointer.from_utf8 to_codeset
9
+ from_ptr = GirFFI::InPointer.from_utf8 from_codeset
10
10
  result_ptr = Lib.g_iconv_open(to_ptr, from_ptr)
11
11
  wrap(result_ptr)
12
12
  end
@@ -10,18 +10,26 @@ module GLib
10
10
  get_string_without_override.first
11
11
  end
12
12
 
13
+ alias_method :get_string_without_override, :get_string
14
+ alias_method :get_string, :get_string_with_override
15
+
13
16
  # Initializing method used in constructors. For Variant, this needs to sink
14
17
  # the variant's floating reference.
15
18
  #
16
19
  # NOTE: This is very hard to test since it is not possible to get the
17
20
  # variant's ref count directely. However, there is an error when running
18
21
  # the tests on 32-bit systems.
22
+ # TODO: Move this logic elsewhere
19
23
  def store_pointer(ptr)
20
24
  super
25
+
26
+ # TODO: Ensure ptr is not autorelease
21
27
  ::GLib::Lib.g_variant_ref_sink ptr
22
28
  end
23
29
 
24
- alias_method :get_string_without_override, :get_string
25
- alias_method :get_string, :get_string_with_override
30
+ # TODO: Update ref?
31
+ def self.wrap_copy(val)
32
+ wrap(val)
33
+ end
26
34
  end
27
35
  end
@@ -4,13 +4,12 @@ require 'gir_ffi/core'
4
4
  # Bypass check for existing modules
5
5
  GirFFI::Builders::ModuleBuilder.new('GObject').generate
6
6
 
7
- require 'ffi-gobject/base'
8
-
9
7
  require 'ffi-gobject/value'
10
8
  require 'ffi-gobject/initially_unowned'
11
9
  require 'ffi-gobject/closure'
12
10
  require 'ffi-gobject/object'
13
11
  require 'ffi-gobject/object_class'
12
+ require 'ffi-gobject/param_spec'
14
13
  require 'ffi-gobject/ruby_closure'
15
14
  require 'gir_ffi/signal_not_found_error'
16
15
 
@@ -19,7 +18,7 @@ module GObject
19
18
  def self.type_from_instance_pointer(inst_ptr)
20
19
  return nil if inst_ptr.null?
21
20
  klsptr = inst_ptr.get_pointer 0
22
- GirFFI::InOutPointer.new(:GType, klsptr).to_value
21
+ klsptr.get_gtype 0
23
22
  end
24
23
 
25
24
  def self.type_from_instance(instance)
@@ -76,14 +75,6 @@ module GObject
76
75
  signal_connect object, detailed_signal, data, true, &block
77
76
  end
78
77
 
79
- # Smells of :reek:LongParameterList: due to the C interface.
80
- # rubocop:disable Metrics/ParameterLists
81
- def self.param_spec_int(name, nick, blurb, minimum, maximum, default_value, flags)
82
- ptr = Lib.g_param_spec_int(name, nick, blurb, minimum, maximum,
83
- default_value, flags)
84
- ParamSpecInt.wrap(ptr)
85
- end
86
-
87
78
  load_class :Callback
88
79
  load_class :ClosureNotify
89
80
  load_class :ConnectFlags
@@ -96,6 +87,8 @@ module GObject
96
87
  attach_function :g_object_ref, [:pointer], :pointer
97
88
  attach_function :g_object_unref, [:pointer], :pointer
98
89
 
90
+ attach_function :g_value_copy, [:pointer, :pointer], :void
91
+ attach_function :g_value_init, [:pointer, :size_t], :pointer
99
92
  attach_function :g_value_unset, [:pointer], :pointer
100
93
 
101
94
  attach_function :g_array_get_type, [], :size_t
@@ -109,9 +102,8 @@ module GObject
109
102
  attach_function :g_closure_set_marshal,
110
103
  [:pointer, ClosureMarshal], :void
111
104
 
112
- attach_function :g_param_spec_int,
113
- [:string, :string, :string, :int32, :int32, :int32, ParamFlags],
114
- :pointer
105
+ attach_function :g_param_spec_ref, [:pointer], :pointer
106
+ attach_function :g_param_spec_sink, [:pointer], :pointer
115
107
  end
116
108
 
117
109
  TYPE_ARRAY = Lib.g_array_get_type
@@ -26,6 +26,13 @@ module GObject
26
26
 
27
27
  private :base_initialize
28
28
 
29
+ remove_method :ref
30
+
31
+ def ref
32
+ Lib.g_object_ref self
33
+ self
34
+ end
35
+
29
36
  def store_pointer(ptr)
30
37
  super
31
38
  klass = self.class
@@ -13,7 +13,7 @@ module GObject
13
13
  end
14
14
 
15
15
  def gtype
16
- GirFFI::InOutPointer.new(:GType, to_ptr).to_value
16
+ to_ptr.get_gtype 0
17
17
  end
18
18
  end
19
19
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ GObject.load_class :ParamSpec
3
+
4
+ module GObject
5
+ # Overrides for GParamSpec, GObject's base class for parameter specifications.
6
+ class ParamSpec
7
+ def ref
8
+ Lib.g_param_spec_ref self
9
+ self
10
+ end
11
+ end
12
+ end
@@ -4,17 +4,13 @@ GObject.load_class :Value
4
4
  module GObject
5
5
  # Overrides for GValue, GObject's generic value container structure.
6
6
  class Value
7
- setup_instance_method 'init'
7
+ remove_method :init
8
8
 
9
- def init_with_finalizer(type)
10
- return self if [TYPE_NONE, TYPE_INVALID].include? type
11
- init_without_finalizer(type)
9
+ def init(type)
10
+ Lib.g_value_init self, type unless [TYPE_NONE, TYPE_INVALID].include? type
12
11
  self
13
12
  end
14
13
 
15
- alias_method :init_without_finalizer, :init
16
- alias_method :init, :init_with_finalizer
17
-
18
14
  def self.make_finalizer(struct, gtype)
19
15
  proc do
20
16
  ptr = struct.to_ptr
@@ -115,10 +111,22 @@ module GObject
115
111
 
116
112
  def self.copy_value_to_pointer(value, pointer, offset = 0)
117
113
  super(value, pointer, offset).tap do
114
+ # FIXME: Check if this is still needed.
118
115
  value.to_ptr.autorelease = false if value
119
116
  end
120
117
  end
121
118
 
119
+ def self.copy(val)
120
+ return unless val
121
+ result = for_gtype(val.current_gtype)
122
+ Lib.g_value_copy val, result unless val.uninitialized?
123
+ result
124
+ end
125
+
126
+ def uninitialized?
127
+ current_gtype == TYPE_INVALID
128
+ end
129
+
122
130
  private
123
131
 
124
132
  def set_ruby_value(val)
@@ -150,10 +158,6 @@ module GObject
150
158
  def get_none
151
159
  end
152
160
 
153
- def uninitialized?
154
- current_gtype == TYPE_INVALID
155
- end
156
-
157
161
  def set_instance_enhanced(val)
158
162
  check_type_compatibility val if val
159
163
  set_instance val
@@ -203,5 +207,10 @@ module GObject
203
207
  METHOD_MAP[current_gtype] || METHOD_MAP[current_fundamental_type] ||
204
208
  raise("No method map entry for #{current_gtype_name}")
205
209
  end
210
+
211
+ def make_finalizer
212
+ gtype = self.class.gtype
213
+ ObjectSpace.define_finalizer self, self.class.make_finalizer(@struct, gtype)
214
+ end
206
215
  end
207
216
  end
@@ -1,13 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Ensure GLib is defined by GirFFI itself
3
+ # Ensure GObject is defined by GirFFI itself
4
4
  raise 'The module GObject was already defined elsewhere' if Kernel.const_defined? :GObject
5
5
 
6
+ require 'gir_ffi-base/gobject/lib'
7
+
6
8
  # The part of the GObject namespace that is needed by GObjectIntrospection.
7
9
  module GObject
8
10
  def self.type_init
9
11
  Lib.g_type_init
10
12
  end
11
- end
12
13
 
13
- require 'gir_ffi-base/gobject/lib'
14
+ def self.type_from_name(name)
15
+ Lib.g_type_from_name name
16
+ end
17
+
18
+ def self.type_fundamental(gtype)
19
+ Lib.g_type_fundamental gtype
20
+ end
21
+
22
+ TYPE_INVALID = type_from_name('invalid')
23
+ TYPE_NONE = type_from_name('void')
24
+ TYPE_INTERFACE = type_from_name('GInterface')
25
+ TYPE_CHAR = type_from_name('gchar')
26
+ TYPE_UCHAR = type_from_name('guchar')
27
+ TYPE_BOOLEAN = type_from_name('gboolean')
28
+ TYPE_INT = type_from_name('gint')
29
+ TYPE_UINT = type_from_name('guint')
30
+ TYPE_LONG = type_from_name('glong')
31
+ TYPE_ULONG = type_from_name('gulong')
32
+ TYPE_INT64 = type_from_name('gint64')
33
+ TYPE_UINT64 = type_from_name('guint64')
34
+ TYPE_ENUM = type_from_name('GEnum')
35
+ TYPE_FLAGS = type_from_name('GFlags')
36
+ TYPE_FLOAT = type_from_name('gfloat')
37
+ TYPE_DOUBLE = type_from_name('gdouble')
38
+ TYPE_STRING = type_from_name('gchararray')
39
+ TYPE_POINTER = type_from_name('gpointer')
40
+ TYPE_BOXED = type_from_name('GBoxed')
41
+ TYPE_PARAM = type_from_name('GParam')
42
+ TYPE_OBJECT = type_from_name('GObject')
43
+ TYPE_GTYPE = type_from_name('GType')
44
+ TYPE_VARIANT = type_from_name('GVariant')
45
+ end
@@ -15,5 +15,7 @@ module GObject
15
15
  extend FFI::BitMasks
16
16
  ffi_lib 'gobject-2.0'
17
17
  attach_function :g_type_init, [], :void
18
+ attach_function :g_type_from_name, [:string], :size_t
19
+ attach_function :g_type_fundamental, [:size_t], :size_t
18
20
  end
19
21
  end
@@ -5,10 +5,21 @@ module GirFFI
5
5
  # Helper module providing a safe allocation method that raises an exception
6
6
  # if memory cannot be allocated.
7
7
  module AllocationHelper
8
+ # NOTE: It would be preferable to use FFI::MemoryPointer.new(size), but
9
+ # there is a bug in FFI which means this gives a problem:
10
+ # # let ptr be a pointer not allocated by FFI.
11
+ # ptr2 = FFI::MemoryPointer.new(1)
12
+ # ptr.put_pointer ptr2 # This raises an out-of-bounds error.
13
+ # This occurs in method_int8_arg_and_out_callee
8
14
  def self.safe_malloc(size)
9
15
  ptr = LibC.malloc size
10
16
  raise NoMemoryError if ptr.null?
11
17
  ptr
12
18
  end
19
+
20
+ def self.allocate(type)
21
+ type_size = FFI.type_size type
22
+ safe_malloc(type_size)
23
+ end
13
24
  end
14
25
  end
@@ -63,5 +63,9 @@ module GirFFI
63
63
  def self.cast_pointer_to_int32(ptr)
64
64
  cast_uint32_to_int32(ptr.address & 0xffffffff)
65
65
  end
66
+
67
+ def self.store(obj)
68
+ OBJECT_STORE.store(obj)
69
+ end
66
70
  end
67
71
  end
@@ -3,50 +3,46 @@ require 'gir_ffi/class_base'
3
3
 
4
4
  module GirFFI
5
5
  # Base class for generated classes representing boxed types.
6
- class BoxedBase < ClassBase
7
- extend FFI::DataConverter
8
-
9
- def self.native_type
10
- FFI::Type::Struct.new(self::Struct)
6
+ class BoxedBase < StructBase
7
+ def initialize
8
+ store_pointer(self.class::Struct.new.to_ptr)
11
9
  end
12
10
 
13
- def self.to_ffi_type
14
- self
11
+ def self.make_finalizer(ptr, gtype)
12
+ proc do
13
+ if ptr.autorelease?
14
+ ptr.autorelease = false
15
+ GObject.boxed_free gtype, ptr
16
+ end
17
+ end
15
18
  end
16
19
 
17
- # NOTE: Needed for JRuby's FFI
18
- def self.to_native(value, _context)
19
- value.struct
20
+ # Create an unowned copy of the struct represented by val
21
+ def self.copy_from(val)
22
+ copy from(val)
20
23
  end
21
24
 
22
- def self.get_value_from_pointer(pointer, offset)
23
- pointer + offset
25
+ # Wrap an owned copy of the struct represented by val
26
+ def self.wrap_copy(val)
27
+ copy(wrap(val)).tap { |it| it && it.to_ptr.autorelease = true }
24
28
  end
25
29
 
26
- def self.copy_value_to_pointer(value, pointer, offset = 0)
27
- size = self::Struct.size
28
- bytes = if value
29
- value.to_ptr.read_bytes(size)
30
- else
31
- "\x00" * size
32
- end
33
- pointer.put_bytes offset, bytes, 0, size
30
+ def self.copy(val)
31
+ return unless val
32
+ ptr = GObject.boxed_copy(gtype, val)
33
+ wrap(ptr)
34
34
  end
35
35
 
36
- def initialize
37
- @struct = self.class::Struct.new
38
- gtype = self.class.gtype
39
- if GObject.type_fundamental(gtype) == GObject::TYPE_BOXED
40
- ObjectSpace.define_finalizer self, self.class.make_finalizer(@struct, gtype)
41
- end
36
+ private
37
+
38
+ def store_pointer(ptr)
39
+ super
40
+ make_finalizer
42
41
  end
43
42
 
44
- def self.make_finalizer(struct, gtype)
45
- proc do
46
- ptr = struct.to_ptr
47
- ptr.autorelease = false
48
- GObject.boxed_free gtype, struct.to_ptr
49
- end
43
+ def make_finalizer
44
+ gtype = self.class.gtype
45
+ ObjectSpace.define_finalizer self, self.class.make_finalizer(to_ptr, gtype)
50
46
  end
51
47
  end
52
48
  end
@@ -3,6 +3,7 @@ require 'gir_ffi/builders/base_argument_builder'
3
3
  require 'gir_ffi/builders/closure_to_pointer_convertor'
4
4
  require 'gir_ffi/builders/full_c_to_ruby_convertor'
5
5
  require 'gir_ffi/builders/ruby_to_c_convertor'
6
+ require 'gir_ffi/builders/pointer_value_convertor'
6
7
  require 'gir_ffi/builders/null_convertor'
7
8
 
8
9
  module GirFFI
@@ -51,7 +52,7 @@ module GirFFI
51
52
  pr << "#{call_argument_name} = #{ingoing_convertor.conversion}"
52
53
  when :inout
53
54
  pr << out_parameter_preparation
54
- pr << "#{call_argument_name}.set_value #{ingoing_convertor.conversion}"
55
+ pr << ingoing_value_storage
55
56
  when :out
56
57
  pr << out_parameter_preparation
57
58
  when :error
@@ -73,6 +74,11 @@ module GirFFI
73
74
 
74
75
  private
75
76
 
77
+ def ingoing_value_storage
78
+ PointerValueConvertor.new(type_spec).
79
+ value_to_pointer(call_argument_name, ingoing_convertor.conversion)
80
+ end
81
+
76
82
  def has_post_conversion?
77
83
  has_output_value? && (!caller_allocated_object? || gvalue?)
78
84
  end
@@ -81,16 +87,29 @@ module GirFFI
81
87
  if caller_allocated_object? && gvalue?
82
88
  return "#{call_argument_name}.get_value"
83
89
  end
84
- base = "#{call_argument_name}.to_value"
90
+ base = pointer_to_value_method_call call_argument_name, type_spec
85
91
  if needs_out_conversion?
86
- FullCToRubyConvertor.new(@type_info, base, length_argument_name).conversion
92
+ outgoing_convertor(base).conversion
87
93
  elsif allocated_by_them?
88
- "GirFFI::InOutPointer.new(#{type_info.tag_or_class[1].inspect}, #{base}).to_value"
94
+ pointer_to_value_method_call base, sub_type_spec
89
95
  else
90
96
  base
91
97
  end
92
98
  end
93
99
 
100
+ def outgoing_convertor(base)
101
+ FullCToRubyConvertor.new(@type_info, base, length_argument_name,
102
+ ownership_transfer: @arginfo.ownership_transfer)
103
+ end
104
+
105
+ def sub_type_spec
106
+ type_spec[1]
107
+ end
108
+
109
+ def pointer_to_value_method_call(ptr_exp, spec)
110
+ PointerValueConvertor.new(spec).pointer_to_value(ptr_exp)
111
+ end
112
+
94
113
  def needs_out_conversion?
95
114
  @type_info.needs_c_to_ruby_conversion_for_functions?
96
115
  end
@@ -154,11 +173,16 @@ module GirFFI
154
173
  "#{argument_class_name}.new"
155
174
  end
156
175
  else
157
- "GirFFI::InOutPointer.for #{type_info.tag_or_class.inspect}"
176
+ ffi_type_spec = TypeMap.type_specification_to_ffi_type type_spec
177
+ "FFI::MemoryPointer.new #{ffi_type_spec.inspect}"
158
178
  end
159
179
  "#{call_argument_name} = #{value}"
160
180
  end
161
181
 
182
+ def type_spec
183
+ type_info.tag_or_class
184
+ end
185
+
162
186
  def caller_allocated_object?
163
187
  [:struct, :array].include?(specialized_type_tag) &&
164
188
  @arginfo.caller_allocates?
@@ -174,7 +198,8 @@ module GirFFI
174
198
  elsif closure?
175
199
  ClosureToPointerConvertor.new(pre_convertor_argument, @is_closure)
176
200
  elsif @type_info.needs_ruby_to_c_conversion_for_functions?
177
- RubyToCConvertor.new(@type_info, pre_convertor_argument)
201
+ RubyToCConvertor.new(@type_info, pre_convertor_argument,
202
+ ownership_transfer: ownership_transfer)
178
203
  else
179
204
  NullConvertor.new(pre_convertor_argument)
180
205
  end