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
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