gir_ffi 0.7.3 → 0.7.4

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