gir_ffi 0.7.3 → 0.7.4

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +10 -0
  3. data/Rakefile +9 -1
  4. data/TODO.md +4 -0
  5. data/lib/ffi-glib.rb +5 -0
  6. data/lib/ffi-glib/bytes.rb +49 -0
  7. data/lib/ffi-glib/container_class_methods.rb +1 -4
  8. data/lib/ffi-glib/error.rb +17 -0
  9. data/lib/ffi-gobject/value.rb +6 -3
  10. data/lib/ffi-gobject_introspection/i_callback_info.rb +0 -1
  11. data/lib/ffi-gobject_introspection/i_constant_info.rb +10 -10
  12. data/lib/ffi-gobject_introspection/i_repository.rb +20 -20
  13. data/lib/ffi-gobject_introspection/i_vfunc_info.rb +7 -0
  14. data/lib/ffi-gobject_introspection/lib.rb +1 -7
  15. data/lib/gir_ffi/arg_helper.rb +23 -2
  16. data/lib/gir_ffi/builders/argument_builder.rb +15 -1
  17. data/lib/gir_ffi/builders/base_argument_builder.rb +1 -0
  18. data/lib/gir_ffi/builders/callback_argument_builder.rb +49 -7
  19. data/lib/gir_ffi/builders/callback_return_value_builder.rb +6 -2
  20. data/lib/gir_ffi/builders/closure_convertor.rb +1 -1
  21. data/lib/gir_ffi/builders/null_convertor.rb +1 -0
  22. data/lib/gir_ffi/builders/property_builder.rb +1 -1
  23. data/lib/gir_ffi/builders/return_value_builder.rb +1 -1
  24. data/lib/gir_ffi/builders/type_builder.rb +9 -9
  25. data/lib/gir_ffi/builders/vfunc_builder.rb +3 -1
  26. data/lib/gir_ffi/callback_base.rb +6 -0
  27. data/lib/gir_ffi/error_argument_info.rb +12 -3
  28. data/lib/gir_ffi/error_type_info.rb +21 -0
  29. data/lib/gir_ffi/ffi_ext/pointer.rb +5 -6
  30. data/lib/gir_ffi/glib_error.rb +18 -0
  31. data/lib/gir_ffi/in_pointer.rb +1 -1
  32. data/lib/gir_ffi/info_ext/i_type_info.rb +44 -30
  33. data/lib/gir_ffi/info_ext/i_vfunc_info.rb +13 -1
  34. data/lib/gir_ffi/type_map.rb +30 -29
  35. data/lib/gir_ffi/user_defined_type_info.rb +1 -0
  36. data/lib/gir_ffi/version.rb +1 -1
  37. data/lib/gir_ffi/vfunc_base.rb +1 -0
  38. data/lib/gir_ffi/zero_terminated.rb +3 -8
  39. data/test/base_test_helper.rb +1 -0
  40. data/test/ffi-glib/array_test.rb +2 -2
  41. data/test/ffi-glib/bytes_test.rb +54 -0
  42. data/test/ffi-glib/ptr_array_test.rb +2 -2
  43. data/test/ffi-gobject/value_test.rb +4 -4
  44. data/test/ffi-gobject_introspection/i_repository_test.rb +1 -1
  45. data/test/gir_ffi/builders/callback_argument_builder_test.rb +44 -0
  46. data/test/gir_ffi/builders/callback_builder_test.rb +1 -1
  47. data/test/gir_ffi/builders/callback_return_value_builder_test.rb +74 -0
  48. data/test/gir_ffi/builders/function_builder_test.rb +23 -2
  49. data/test/gir_ffi/builders/property_builder_test.rb +15 -0
  50. data/test/gir_ffi/builders/return_value_builder_test.rb +26 -26
  51. data/test/gir_ffi/builders/signal_builder_test.rb +5 -5
  52. data/test/gir_ffi/builders/union_builder_test.rb +2 -1
  53. data/test/gir_ffi/builders/vfunc_builder_test.rb +125 -4
  54. data/test/gir_ffi/error_type_info_test.rb +48 -0
  55. data/test/gir_ffi/in_pointer_test.rb +1 -1
  56. data/test/gir_ffi/sized_array_test.rb +2 -2
  57. data/test/integration/generated_gimarshallingtests_test.rb +199 -31
  58. data/test/integration/generated_regress_test.rb +37 -33
  59. metadata +214 -202
@@ -30,7 +30,11 @@ module GirFFI
30
30
 
31
31
  def post_conversion
32
32
  if has_post_conversion?
33
- [ "#{post_converted_name} = #{post_convertor.conversion}" ]
33
+ if type_info.flattened_tag == :object
34
+ [ "#{post_converted_name} = #{post_convertor.conversion}.to_ptr" ]
35
+ else
36
+ [ "#{post_converted_name} = #{post_convertor.conversion}" ]
37
+ end
34
38
  else
35
39
  []
36
40
  end
@@ -39,7 +43,7 @@ module GirFFI
39
43
  private
40
44
 
41
45
  def has_post_conversion?
42
- type_info.needs_conversion_for_callbacks?
46
+ type_info.needs_c_to_ruby_conversion_for_callbacks?
43
47
  end
44
48
 
45
49
  def post_convertor
@@ -4,6 +4,6 @@ class GirFFI::Builders::ClosureConvertor
4
4
  end
5
5
 
6
6
  def conversion
7
- "GirFFI::ArgHelper::OBJECT_STORE[#{@argument_name}.address]"
7
+ "GirFFI::ArgHelper::OBJECT_STORE.fetch(#{@argument_name})"
8
8
  end
9
9
  end
@@ -1,3 +1,4 @@
1
+ # Argument convertor that does nothing
1
2
  class GirFFI::Builders::NullConvertor
2
3
  def initialize argument_name
3
4
  @argument_name = argument_name
@@ -16,7 +16,7 @@ module GirFFI
16
16
  end
17
17
 
18
18
  def container_defines_getter_method?
19
- container_info.find_instance_method @info.name
19
+ container_info.find_instance_method getter_name
20
20
  end
21
21
 
22
22
  def setup_setter
@@ -46,7 +46,7 @@ module GirFFI
46
46
 
47
47
  def has_post_conversion?
48
48
  is_closure || needs_constructor_wrap? ||
49
- type_info.needs_conversion_for_functions?
49
+ type_info.needs_c_to_ruby_conversion_for_functions?
50
50
  end
51
51
 
52
52
  def post_convertor
@@ -17,15 +17,15 @@ module GirFFI
17
17
  CACHE = {}
18
18
 
19
19
  TYPE_MAP = {
20
- :callback => CallbackBuilder,
21
- :constant => ConstantBuilder,
22
- :enum => EnumBuilder,
23
- :flags => EnumBuilder,
24
- :interface => InterfaceBuilder,
25
- :object => ObjectBuilder,
26
- :struct => StructBuilder,
27
- :union => UnionBuilder,
28
- :unintrospectable => UnintrospectableBuilder
20
+ callback: CallbackBuilder,
21
+ constant: ConstantBuilder,
22
+ enum: EnumBuilder,
23
+ flags: EnumBuilder,
24
+ interface: InterfaceBuilder,
25
+ object: ObjectBuilder,
26
+ struct: StructBuilder,
27
+ union: UnionBuilder,
28
+ unintrospectable: UnintrospectableBuilder
29
29
  }
30
30
 
31
31
  def self.build info
@@ -25,6 +25,7 @@ module GirFFI
25
25
 
26
26
  def mapping_method_definition
27
27
  arg_infos = info.args
28
+ arg_infos << ErrorArgumentInfo.new if info.throws?
28
29
 
29
30
  receiver_info = ReceiverArgumentInfo.new(receiver_type_info)
30
31
 
@@ -46,7 +47,8 @@ module GirFFI
46
47
  end
47
48
 
48
49
  def argument_ffi_types
49
- @argument_ffi_types ||= info.argument_ffi_types.unshift(receiver_type_info.to_ffitype)
50
+ @argument_ffi_types ||= info.argument_ffi_types.
51
+ unshift(receiver_type_info.to_callback_ffitype)
50
52
  end
51
53
 
52
54
  def return_ffi_type
@@ -2,6 +2,8 @@ require 'gir_ffi/type_base'
2
2
 
3
3
  module GirFFI
4
4
  # Base module for callbacks.
5
+ # NOTE: Another option would be to derive this class from FFI::Function,
6
+ # allowing a more natural implementation of from_native, to_native and wrap.
5
7
  class CallbackBase < Proc
6
8
  extend TypeBase
7
9
  extend FFI::DataConverter
@@ -22,6 +24,10 @@ module GirFFI
22
24
  value.to_native
23
25
  end
24
26
 
27
+ def self.wrap ptr
28
+ from_native ptr, nil
29
+ end
30
+
25
31
  CALLBACKS = []
26
32
 
27
33
  def self.store_callback prc
@@ -1,3 +1,5 @@
1
+ require 'gir_ffi/error_type_info'
2
+
1
3
  module GirFFI
2
4
  # Represents an error argument with the same interface as IArgumentInfo
3
5
  class ErrorArgumentInfo
@@ -10,12 +12,19 @@ module GirFFI
10
12
  end
11
13
 
12
14
  def argument_type
13
- nil
15
+ @argument_type ||= ErrorTypeInfo.new
14
16
  end
15
17
 
16
18
  def name
17
- nil
19
+ "_error"
20
+ end
21
+
22
+ def closure
23
+ -1
24
+ end
25
+
26
+ def caller_allocates?
27
+ true
18
28
  end
19
29
  end
20
30
  end
21
-
@@ -0,0 +1,21 @@
1
+ require 'gir_ffi/info_ext/i_type_info'
2
+
3
+ module GirFFI
4
+ # Represents the type of an error argument for callbacks and functions,
5
+ # conforming, as needed, to the interface of GObjectIntrospection::ITypeInfo
6
+ class ErrorTypeInfo
7
+ include GirFFI::InfoExt::ITypeInfo
8
+
9
+ def array_length
10
+ -1
11
+ end
12
+
13
+ def tag
14
+ :error
15
+ end
16
+
17
+ def pointer?
18
+ true
19
+ end
20
+ end
21
+ end
@@ -9,15 +9,14 @@ module GirFFI
9
9
  self
10
10
  end
11
11
 
12
- def to_object
13
- gtype = GObject.type_from_instance_pointer self
14
- wrap_by_gtype gtype
12
+ def zero?
13
+ null?
15
14
  end
16
15
 
17
- def wrap_by_gtype gtype
16
+ def to_object
18
17
  return nil if self.null?
19
- klass = Builder.build_by_gtype gtype
20
- klass.direct_wrap self
18
+ gtype = GObject.type_from_instance_pointer self
19
+ Builder.build_by_gtype(gtype).direct_wrap self
21
20
  end
22
21
 
23
22
  def to_utf8
@@ -0,0 +1,18 @@
1
+ module GirFFI
2
+ # Exception class to be raised whenever an error is signaled through
3
+ # GLib::Error.
4
+ class GLibError < RuntimeError
5
+ attr_reader :domain_quark
6
+ attr_reader :code
7
+
8
+ def initialize g_error
9
+ @domain_quark = g_error.domain
10
+ @code = g_error.code
11
+ super g_error.message
12
+ end
13
+
14
+ def domain
15
+ @domain ||= GLib.quark_to_string @domain_quark
16
+ end
17
+ end
18
+ end
@@ -48,7 +48,7 @@ module GirFFI
48
48
  class << self
49
49
  def from_closure_data obj
50
50
  FFI::Pointer.new(obj.object_id).tap {|ptr|
51
- ArgHelper::OBJECT_STORE[ptr.address] = obj }
51
+ ArgHelper::OBJECT_STORE.store(ptr, obj) }
52
52
  end
53
53
 
54
54
  private
@@ -7,16 +7,16 @@ module GirFFI
7
7
 
8
8
  def self.flattened_tag_to_gtype_map
9
9
  @flattened_tag_to_gtype_map ||= {
10
- :array => GObject::TYPE_ARRAY,
11
- :c => GObject::TYPE_POINTER,
12
- :gboolean => GObject::TYPE_BOOLEAN,
13
- :ghash => GObject::TYPE_HASH_TABLE,
14
- :gint32 => GObject::TYPE_INT,
15
- :gint64 => GObject::TYPE_INT64,
16
- :guint64 => GObject::TYPE_UINT64,
17
- :strv => GObject::TYPE_STRV,
18
- :utf8 => GObject::TYPE_STRING,
19
- :void => GObject::TYPE_NONE
10
+ array: GObject::TYPE_ARRAY,
11
+ c: GObject::TYPE_POINTER,
12
+ gboolean: GObject::TYPE_BOOLEAN,
13
+ ghash: GObject::TYPE_HASH_TABLE,
14
+ gint32: GObject::TYPE_INT,
15
+ gint64: GObject::TYPE_INT64,
16
+ guint64: GObject::TYPE_UINT64,
17
+ strv: GObject::TYPE_STRV,
18
+ utf8: GObject::TYPE_STRING,
19
+ void: GObject::TYPE_NONE
20
20
  }
21
21
  end
22
22
 
@@ -76,18 +76,18 @@ module GirFFI
76
76
  end
77
77
 
78
78
  TAG_TO_WRAPPER_CLASS_MAP = {
79
- :array => 'GLib::Array',
80
- :byte_array => 'GLib::ByteArray',
81
- :c => 'GirFFI::SizedArray',
82
- :error => 'GLib::Error',
83
- :ghash => 'GLib::HashTable',
84
- :glist => 'GLib::List',
85
- :gslist => 'GLib::SList',
86
- :ptr_array => 'GLib::PtrArray',
87
- :strv => 'GLib::Strv',
88
- :utf8 => 'GirFFI::InPointer',
89
- :void => 'GirFFI::InPointer',
90
- :zero_terminated => 'GirFFI::ZeroTerminated'
79
+ array: 'GLib::Array',
80
+ byte_array: 'GLib::ByteArray',
81
+ c: 'GirFFI::SizedArray',
82
+ error: 'GLib::Error',
83
+ ghash: 'GLib::HashTable',
84
+ glist: 'GLib::List',
85
+ gslist: 'GLib::SList',
86
+ ptr_array: 'GLib::PtrArray',
87
+ strv: 'GLib::Strv',
88
+ utf8: 'GirFFI::InPointer',
89
+ void: 'GirFFI::InPointer',
90
+ zero_terminated: 'GirFFI::ZeroTerminated'
91
91
  }
92
92
 
93
93
  # TODO: Use class rather than class name
@@ -127,19 +127,33 @@ module GirFFI
127
127
  end
128
128
  end
129
129
 
130
+ TAGS_NEEDING_RUBY_TO_C_CONVERSION = [
131
+ :array, :c, :callback, :error, :ghash, :glist, :gslist, :object,
132
+ :ptr_array, :struct, :strv, :utf8, :void, :zero_terminated
133
+ ]
134
+
135
+ TAGS_NEEDING_C_TO_RUBY_CONVERSION = [
136
+ :array, :byte_array, :c, :error, :filename, :ghash, :glist, :gslist,
137
+ :interface, :object, :ptr_array, :struct, :strv, :union, :utf8,
138
+ :zero_terminated
139
+ ]
140
+
130
141
  def needs_ruby_to_c_conversion_for_functions?
131
- [ :array, :c, :callback, :ghash, :glist, :gslist, :object, :ptr_array,
132
- :struct, :strv, :utf8, :void, :zero_terminated ].include?(flattened_tag)
142
+ TAGS_NEEDING_RUBY_TO_C_CONVERSION.include?(flattened_tag)
143
+ end
144
+
145
+ def needs_c_to_ruby_conversion_for_functions?
146
+ TAGS_NEEDING_C_TO_RUBY_CONVERSION.include?(flattened_tag)
133
147
  end
134
148
 
135
- def needs_conversion_for_functions?
136
- [ :array, :byte_array, :c, :error, :filename, :ghash, :glist,
137
- :gslist, :interface, :object, :ptr_array, :struct, :strv, :union,
138
- :utf8, :zero_terminated ].include?(flattened_tag)
149
+ def needs_ruby_to_c_conversion_for_callbacks?
150
+ [:enum].include?(flattened_tag) ||
151
+ needs_ruby_to_c_conversion_for_functions?
139
152
  end
140
153
 
141
- def needs_conversion_for_callbacks?
142
- flattened_tag == :enum || needs_conversion_for_functions?
154
+ def needs_c_to_ruby_conversion_for_callbacks?
155
+ [:callback, :enum].include?(flattened_tag) ||
156
+ needs_c_to_ruby_conversion_for_functions?
143
157
  end
144
158
 
145
159
  def extra_conversion_arguments
@@ -1,9 +1,21 @@
1
1
  module GirFFI
2
2
  module InfoExt
3
3
  # Extensions for GObjectIntrospection::IVFuncInfo needed by GirFFI
4
+ # TODO: Merge implementation with ICallbackInfo and ISignalInfo extensions.
4
5
  module IVFuncInfo
6
+ def argument_ffi_types
7
+ args.map { |arg| arg.to_callback_ffitype }.tap do |types|
8
+ types << :pointer if throws?
9
+ end
10
+ end
11
+
5
12
  def return_ffi_type
6
- return_type.to_callback_ffitype
13
+ result = return_type.to_callback_ffitype
14
+ if result == GLib::Boolean
15
+ :bool
16
+ else
17
+ result
18
+ end
7
19
  end
8
20
  end
9
21
  end
@@ -3,37 +3,38 @@ require 'gir_ffi/sized_array'
3
3
  module GirFFI
4
4
  module TypeMap
5
5
  sz = FFI.type_size(:size_t) * 8
6
- gtype_type = "uint#{sz}".to_sym
6
+ gsize_type = "uint#{sz}".to_sym
7
7
 
8
8
  TAG_TYPE_MAP = {
9
- :enum => :int32,
10
- :flags => :int32,
11
- :ghash => :pointer,
12
- :glist => :pointer,
13
- :gslist => :pointer,
14
- :strv => :pointer,
15
- :object => :pointer,
16
- :struct => :pointer,
17
- :error => :pointer,
18
- :ptr_array => :pointer,
19
- :array => :pointer,
20
- :c => GirFFI::SizedArray,
21
- :utf8 => :pointer,
22
- :GType => gtype_type,
23
- :gboolean => GLib::Boolean,
24
- :gunichar => :uint32,
25
- :gint8 => :int8,
26
- :guint8 => :uint8,
27
- :gint16 => :int16,
28
- :guint16 => :uint16,
29
- :gint => :int,
30
- :gint32 => :int32,
31
- :guint32 => :uint32,
32
- :gint64 => :int64,
33
- :guint64 => :uint64,
34
- :gfloat => :float,
35
- :gdouble => :double,
36
- :void => :void
9
+ enum: :int32,
10
+ flags: :int32,
11
+ ghash: :pointer,
12
+ glist: :pointer,
13
+ gslist: :pointer,
14
+ strv: :pointer,
15
+ object: :pointer,
16
+ struct: :pointer,
17
+ error: :pointer,
18
+ ptr_array: :pointer,
19
+ array: :pointer,
20
+ c: GirFFI::SizedArray,
21
+ utf8: :pointer,
22
+ GType: gsize_type,
23
+ gboolean: GLib::Boolean,
24
+ gunichar: :uint32,
25
+ gint8: :int8,
26
+ guint8: :uint8,
27
+ gint16: :int16,
28
+ guint16: :uint16,
29
+ gint: :int,
30
+ gint32: :int32,
31
+ guint32: :uint32,
32
+ gint64: :int64,
33
+ guint64: :uint64,
34
+ gsize: gsize_type,
35
+ gfloat: :float,
36
+ gdouble: :double,
37
+ void: :void
37
38
  }
38
39
 
39
40
  def self.map_basic_type type
@@ -4,6 +4,7 @@ require 'gir_ffi/vfunc_implementation'
4
4
  module GirFFI
5
5
  # Represents a user defined type, conforming, as needed, to the interface of
6
6
  # GObjectIntrospection::IObjectInfo.
7
+ # TODO: Rename to UserDefinedObjectInfo
7
8
  class UserDefinedTypeInfo
8
9
  attr_reader :properties, :vfunc_implementations
9
10
 
@@ -1,3 +1,3 @@
1
1
  module GirFFI
2
- VERSION = "0.7.3"
2
+ VERSION = "0.7.4"
3
3
  end
@@ -2,6 +2,7 @@ require 'gir_ffi/callback_base'
2
2
 
3
3
  module GirFFI
4
4
  # Base class for virtual methods (vfuncs).
5
+ # FIXME: Inheritence direction is arbitrary.
5
6
  class VFuncBase < CallbackBase
6
7
  end
7
8
  end
@@ -39,7 +39,7 @@ module GirFFI
39
39
 
40
40
  def read_value offset
41
41
  val = @ptr.send(getter_method, offset)
42
- return val unless is_null_value?(val)
42
+ val unless val.zero?
43
43
  end
44
44
 
45
45
  def getter_method
@@ -61,13 +61,8 @@ module GirFFI
61
61
  @ffi_type ||= TypeMap.type_specification_to_ffitype element_type
62
62
  end
63
63
 
64
- def is_null_value? value
65
- if ffi_type == :pointer
66
- value.null?
67
- else
68
- value == 0
69
- end
64
+ def ffi_type_size
65
+ @ffi_type_size ||= FFI.type_size(ffi_type)
70
66
  end
71
67
  end
72
68
  end
73
-