gir_ffi 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/History.txt +5 -0
  2. data/lib/ffi-glib/array.rb +2 -3
  3. data/lib/ffi-glib/container_class_methods.rb +3 -4
  4. data/lib/ffi-glib/hash_table.rb +7 -3
  5. data/lib/ffi-glib/list_methods.rb +1 -1
  6. data/lib/ffi-glib/sized_array.rb +66 -0
  7. data/lib/ffi-glib/strv.rb +1 -1
  8. data/lib/ffi-glib.rb +5 -4
  9. data/lib/ffi-gobject/object.rb +2 -3
  10. data/lib/ffi-gobject/ruby_closure.rb +3 -2
  11. data/lib/ffi-gobject/value.rb +26 -14
  12. data/lib/ffi-gobject.rb +8 -5
  13. data/lib/ffi-gobject_introspection/g_error.rb +1 -0
  14. data/lib/ffi-gobject_introspection/i_base_info.rb +3 -2
  15. data/lib/ffi-gobject_introspection/i_union_info.rb +21 -8
  16. data/lib/ffi-gobject_introspection/lib.rb +1 -0
  17. data/lib/gir_ffi/argument_builder.rb +8 -20
  18. data/lib/gir_ffi/base_argument_builder.rb +13 -30
  19. data/lib/gir_ffi/builder/module.rb +3 -9
  20. data/lib/gir_ffi/builder/type/base.rb +2 -0
  21. data/lib/gir_ffi/builder/type/callback.rb +2 -2
  22. data/lib/gir_ffi/builder/type/enum.rb +1 -0
  23. data/lib/gir_ffi/builder/type/object.rb +13 -3
  24. data/lib/gir_ffi/builder/type/registered_type.rb +1 -1
  25. data/lib/gir_ffi/builder/type/struct.rb +18 -3
  26. data/lib/gir_ffi/builder/type/unintrospectable.rb +5 -45
  27. data/lib/gir_ffi/builder/type/user_defined.rb +3 -15
  28. data/lib/gir_ffi/builder/type.rb +5 -5
  29. data/lib/gir_ffi/builder.rb +5 -80
  30. data/lib/gir_ffi/callback.rb +65 -2
  31. data/lib/gir_ffi/callback_helper.rb +0 -56
  32. data/lib/gir_ffi/class_base.rb +2 -2
  33. data/lib/gir_ffi/in_out_pointer.rb +7 -28
  34. data/lib/gir_ffi/in_pointer.rb +12 -19
  35. data/lib/gir_ffi/info_ext/i_arg_info.rb +5 -0
  36. data/lib/gir_ffi/info_ext/i_callable_info.rb +16 -0
  37. data/lib/gir_ffi/info_ext/i_function_info.rb +15 -0
  38. data/lib/gir_ffi/info_ext/i_signal_info.rb +17 -10
  39. data/lib/gir_ffi/info_ext/i_type_info.rb +63 -39
  40. data/lib/gir_ffi/info_ext.rb +5 -3
  41. data/lib/gir_ffi/null_argument_builder.rb +1 -1
  42. data/lib/gir_ffi/return_value_builder.rb +24 -16
  43. data/lib/gir_ffi/unintrospectable_type_info.rb +41 -0
  44. data/lib/gir_ffi/user_defined_property_info.rb +15 -0
  45. data/lib/gir_ffi/user_defined_type_info.rb +25 -0
  46. data/lib/gir_ffi/version.rb +1 -1
  47. data/lib/gir_ffi-base.rb +3 -0
  48. data/lib/gir_ffi.rb +2 -1
  49. data/test/ffi-glib/sized_array_test.rb +87 -0
  50. data/test/ffi-gobject_introspection/i_base_info_test.rb +4 -5
  51. data/test/gir_ffi/argument_builder_test.rb +26 -55
  52. data/test/gir_ffi/builder/type/unintrospectable_test.rb +3 -19
  53. data/test/gir_ffi/builder/type/user_defined_test.rb +16 -21
  54. data/test/gir_ffi/builder_test.rb +31 -53
  55. data/test/gir_ffi/callback_helper_test.rb +0 -47
  56. data/test/gir_ffi/callback_test.rb +49 -0
  57. data/test/gir_ffi/function_builder_test.rb +8 -8
  58. data/test/gir_ffi/in_out_pointer_test.rb +2 -53
  59. data/test/gir_ffi/in_pointer_test.rb +0 -13
  60. data/test/gir_ffi/info_ext/i_callable_info_test.rb +32 -0
  61. data/test/gir_ffi/info_ext/i_function_info_test.rb +61 -0
  62. data/test/gir_ffi/info_ext/i_signal_info_test.rb +7 -0
  63. data/test/gir_ffi/info_ext/i_type_info_test.rb +158 -77
  64. data/test/gir_ffi/return_value_builder_test.rb +2 -2
  65. data/test/gir_ffi/unintrospectable_type_info_test.rb +95 -0
  66. data/test/gir_ffi/user_defined_property_info_test.rb +19 -0
  67. data/test/gir_ffi/user_defined_type_info_test.rb +34 -0
  68. data/test/integration/generated_gimarshallingtests_test.rb +10 -10
  69. data/test/integration/generated_regress_test.rb +10 -10
  70. metadata +24 -15
  71. data/lib/gir_ffi/builder/type/struct_based.rb +0 -31
  72. data/lib/gir_ffi/user_defined/i_base_info.rb +0 -7
  73. data/lib/gir_ffi/user_defined/i_object_info.rb +0 -13
  74. data/lib/gir_ffi/user_defined/i_property_info.rb +0 -9
  75. data/lib/gir_ffi/user_defined/i_registered_type_info.rb +0 -10
  76. data/test/gir_ffi/user_defined/i_object_info_test.rb +0 -18
  77. data/test/gir_ffi/user_defined/i_property_info_test.rb +0 -14
  78. data/test/gir_ffi/user_defined/i_registered_type_info_test.rb +0 -10
@@ -1,6 +1,7 @@
1
1
  module GirFFI
2
2
  module InfoExt
3
3
  # Extensions for GObjectIntrospection::ISignalInfo needed by GirFFI
4
+ # TODO: Rename methods to not include 'signal' everywhere.
4
5
  module ISignalInfo
5
6
  # Create a signal hander callback. Wraps the given block in such a way that
6
7
  # arguments and return value are cast correctly to the ruby world and back.
@@ -10,7 +11,11 @@ module GirFFI
10
11
  # @return [FFI::Function] The signal handler, ready to be passed as a
11
12
  # callback to C.
12
13
  def signal_callback &block
13
- GirFFI::Builder.build_callback self, &signal_callback_args(&block)
14
+ rettype = self.return_ffi_type
15
+ argtypes = self.ffi_callback_argument_types
16
+
17
+ # TODO: Create signal handler type?
18
+ FFI::Function.new rettype, argtypes, &signal_callback_args(&block)
14
19
  end
15
20
 
16
21
  # TODO: Generate cast back methods using existing Argument builders.
@@ -36,7 +41,7 @@ module GirFFI
36
41
  def signal_arguments_to_gvalue_array instance, *rest
37
42
  arr = ::GObject::ValueArray.new self.n_args + 1
38
43
 
39
- arr.append signal_reciever_to_gvalue instance
44
+ arr.append GObject::Value.wrap_instance(instance)
40
45
 
41
46
  self.args.zip(rest).each do |info, arg|
42
47
  arr.append info.argument_type.make_g_value.set_value(arg)
@@ -49,15 +54,17 @@ module GirFFI
49
54
  GObject::Value.for_g_type return_type.g_type
50
55
  end
51
56
 
52
- private
53
-
54
- def signal_reciever_to_gvalue instance
55
- val = ::GObject::Value.new
56
- val.init ::GObject.type_from_instance instance
57
- val.set_instance instance
58
- return val
57
+ # TODO: Rename and clarify relation to argument_ffi_types:
58
+ # The types returned by ffi_callback_argument_types are more basic than
59
+ # those returned by argument_ffi_types. Is there a way to make these
60
+ # methods more related? Perhaps argument_ffi_types can return more basic
61
+ # types as well?
62
+ def ffi_callback_argument_types
63
+ types = args.map do |arg|
64
+ arg.argument_type.to_callback_ffitype
65
+ end
66
+ types.unshift(:pointer).push(:pointer)
59
67
  end
60
-
61
68
  end
62
69
  end
63
70
  end
@@ -21,12 +21,10 @@ module GirFFI
21
21
  end
22
22
 
23
23
  def layout_specification_type
24
- ffitype = GirFFI::Builder.itypeinfo_to_ffitype self
24
+ ffitype = self.to_ffitype
25
25
  case ffitype
26
26
  when Class
27
27
  ffitype.const_get :Struct
28
- when :bool
29
- :int
30
28
  when :array
31
29
  subtype = param_type(0).layout_specification_type
32
30
  # XXX Don't use pointer directly to appease JRuby.
@@ -42,9 +40,9 @@ module GirFFI
42
40
  def element_type
43
41
  case tag
44
42
  when :glist, :gslist, :array
45
- subtype_tag 0
43
+ subtype_tag_or_class 0
46
44
  when :ghash
47
- [subtype_tag(0), subtype_tag(1)]
45
+ [subtype_tag_or_class(0), subtype_tag_or_class(1)]
48
46
  else
49
47
  nil
50
48
  end
@@ -54,24 +52,15 @@ module GirFFI
54
52
  interface.full_type_name
55
53
  end
56
54
 
57
- def type_specification
58
- tag = self.flattened_tag
59
- case tag
60
- when :strv, :zero_terminated, :c
61
- "[#{tag.inspect}, #{subtype_tag_or_class_name}]"
62
- else
63
- tag.inspect
64
- end
65
- end
66
-
67
55
  def flattened_tag
68
- case tag
56
+ type_tag = self.tag
57
+ case type_tag
69
58
  when :interface
70
59
  interface_type
71
60
  when :array
72
61
  flattened_array_type
73
62
  else
74
- tag
63
+ type_tag
75
64
  end
76
65
  end
77
66
 
@@ -87,21 +76,71 @@ module GirFFI
87
76
  end
88
77
  end
89
78
 
90
- def subtype_tag_or_class_name
91
- type = self.param_type 0
92
- tag = type.tag
93
- base = if tag == :interface
94
- type.interface_type_name
79
+ def subtype_tag_or_class_name index = 0
80
+ param_type(index).tag_or_class_name
81
+ end
82
+
83
+ def subtype_tag_or_class index = 0
84
+ param_type(index).tag_or_class
85
+ end
86
+
87
+ # TODO: Merge with tag_or_class
88
+ def tag_or_class_name
89
+ type_tag = self.tag
90
+ base = if type_tag == :interface
91
+ interface_type_name
95
92
  else
96
- tag.inspect
93
+ type_tag.inspect
97
94
  end
98
- if type.pointer? && tag != :utf8 && tag != :filename
95
+ if pointer? && type_tag != :utf8 && type_tag != :filename
99
96
  "[:pointer, #{base}]"
100
97
  else
101
98
  base
102
99
  end
103
100
  end
104
101
 
102
+ def tag_or_class
103
+ type_tag = self.tag
104
+ base = if type_tag == :interface
105
+ Builder.build_class interface
106
+ else
107
+ type_tag
108
+ end
109
+ if pointer? && type_tag != :utf8 && type_tag != :filename
110
+ [:pointer, base]
111
+ else
112
+ base
113
+ end
114
+ end
115
+
116
+ def to_ffitype
117
+ return :pointer if pointer?
118
+
119
+ type_tag = tag
120
+ if type_tag == :interface
121
+ Builder.build_class interface
122
+ else
123
+ TypeMap.map_basic_type type_tag
124
+ end
125
+ end
126
+
127
+ def to_callback_ffitype
128
+ type_tag = tag
129
+
130
+ return :string if type_tag == :utf8
131
+ return :pointer if pointer?
132
+
133
+ if type_tag == :interface
134
+ case interface.info_type
135
+ when :enum, :flags
136
+ :int32
137
+ else
138
+ :pointer
139
+ end
140
+ else
141
+ return TypeMap.map_basic_type type_tag
142
+ end
143
+ end
105
144
  private
106
145
 
107
146
  def zero_terminated_array_type
@@ -113,21 +152,6 @@ module GirFFI
113
152
  :zero_terminated
114
153
  end
115
154
  end
116
-
117
- def subtype_tag index
118
- st = param_type(index)
119
- tag = st.tag
120
- case tag
121
- when :interface
122
- return :interface_pointer if st.pointer?
123
- return :interface
124
- when :void
125
- return :gpointer if st.pointer?
126
- return :void
127
- else
128
- return tag
129
- end
130
- end
131
155
  end
132
156
  end
133
157
  end
@@ -1,8 +1,10 @@
1
- require 'gir_ffi/info_ext/safe_constant_name'
2
- require 'gir_ffi/info_ext/safe_function_name'
3
1
  require 'gir_ffi/info_ext/i_arg_info'
2
+ require 'gir_ffi/info_ext/i_callable_info'
4
3
  require 'gir_ffi/info_ext/i_field_info'
4
+ require 'gir_ffi/info_ext/i_function_info'
5
5
  require 'gir_ffi/info_ext/i_property_info'
6
- require 'gir_ffi/info_ext/i_signal_info'
7
6
  require 'gir_ffi/info_ext/i_registered_type_info'
7
+ require 'gir_ffi/info_ext/i_signal_info'
8
8
  require 'gir_ffi/info_ext/i_type_info'
9
+ require 'gir_ffi/info_ext/safe_constant_name'
10
+ require 'gir_ffi/info_ext/safe_function_name'
@@ -1,7 +1,7 @@
1
1
  module GirFFI
2
2
  # Argument builder that does nothing. Implements the Null Object pattern.
3
3
  class NullArgumentBuilder
4
- def initialize *args; end
4
+ def initialize *; end
5
5
  def pre; []; end
6
6
  def post; []; end
7
7
  def callarg; end
@@ -9,18 +9,8 @@ module GirFFI
9
9
  end
10
10
 
11
11
  def post
12
- if needs_wrapping?
13
- if [ :interface, :object ].include?(specialized_type_tag) && @is_constructor
14
- [ "#{retname} = self.constructor_wrap(#{cvar})" ]
15
- else
16
- [ "#{retname} = #{argument_class_name}.wrap(#{return_value_conversion_arguments})" ]
17
- end
18
- elsif specialized_type_tag == :utf8
19
- # TODO: Re-use methods in InOutPointer for this conversion
20
- [ "#{retname} = GirFFI::ArgHelper.ptr_to_utf8(#{cvar})" ]
21
- elsif specialized_type_tag == :c
22
- size = array_size
23
- [ "#{retname} = GirFFI::ArgHelper.ptr_to_typed_array #{subtype_tag_or_class_name}, #{cvar}, #{size}" ]
12
+ if has_conversion?
13
+ [ "#{retname} = #{post_conversion}" ]
24
14
  else
25
15
  []
26
16
  end
@@ -47,6 +37,24 @@ module GirFFI
47
37
 
48
38
  private
49
39
 
40
+ def post_conversion
41
+ raw = cvar
42
+
43
+ if needs_constructor_wrap?
44
+ "self.constructor_wrap(#{raw})"
45
+ elsif needs_wrapping?
46
+ "#{argument_class_name}.wrap(#{conversion_arguments raw})"
47
+ else
48
+ case specialized_type_tag
49
+ when :utf8
50
+ # TODO: Re-use methods in InOutPointer for this conversion
51
+ "GirFFI::ArgHelper.ptr_to_utf8(#{raw})"
52
+ when :c
53
+ "GLib::SizedArray.wrap(#{subtype_tag_or_class_name}, #{array_size}, #{raw})"
54
+ end
55
+ end
56
+ end
57
+
50
58
  def retname
51
59
  @retname ||= @var_gen.new_var
52
60
  end
@@ -61,12 +69,12 @@ module GirFFI
61
69
  ].include?(specialized_type_tag)
62
70
  end
63
71
 
64
- def is_void_return_value?
65
- specialized_type_tag == :void && !type_info.pointer?
72
+ def needs_constructor_wrap?
73
+ @is_constructor && [ :interface, :object ].include?(specialized_type_tag)
66
74
  end
67
75
 
68
- def return_value_conversion_arguments
69
- conversion_arguments cvar
76
+ def is_void_return_value?
77
+ specialized_type_tag == :void && !type_info.pointer?
70
78
  end
71
79
  end
72
80
  end
@@ -0,0 +1,41 @@
1
+ module GirFFI
2
+ # Represents a type not found in the GIR, conforming, as needed, to the
3
+ # interface of GObjectIntrospection::IObjectInfo.
4
+ class UnintrospectableTypeInfo
5
+ attr_reader :g_type
6
+
7
+ def initialize(gtype,
8
+ gir = GObjectIntrospection::IRepository.default,
9
+ gobject = ::GObject)
10
+ @g_type = gtype
11
+ @gir = gir
12
+ @gobject = gobject
13
+ end
14
+
15
+ def info_type
16
+ :unintrospectable
17
+ end
18
+
19
+ def safe_name
20
+ @gobject.type_name @g_type
21
+ end
22
+
23
+ def parent
24
+ @gir.find_by_gtype @gobject.type_parent(@g_type)
25
+ end
26
+
27
+ def namespace
28
+ parent.namespace
29
+ end
30
+
31
+ def interfaces
32
+ @gobject.type_interfaces(@g_type).map do |gtype|
33
+ @gir.find_by_gtype gtype
34
+ end.compact
35
+ end
36
+
37
+ def fields
38
+ []
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ module GirFFI
2
+ # Represents a property of a user defined type, conforming, as needed, to the
3
+ # interface of GObjectIntrospection::IPropertyInfo.
4
+ class UserDefinedPropertyInfo
5
+ def initialize param_spec
6
+ @param_spec = param_spec
7
+ end
8
+
9
+ attr_reader :param_spec
10
+
11
+ def name
12
+ @param_spec.get_name
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ require 'gir_ffi/user_defined_property_info'
2
+
3
+ module GirFFI
4
+ # Represents a user defined type, conforming, as needed, to the interface of
5
+ # GObjectIntrospection::IObjectInfo.
6
+ class UserDefinedTypeInfo
7
+ def initialize klass, &block
8
+ @klass = klass
9
+ @properties = []
10
+ self.instance_eval(&block) if block
11
+ end
12
+
13
+ def described_class
14
+ @klass
15
+ end
16
+
17
+ def install_property property
18
+ @properties << UserDefinedPropertyInfo.new(property)
19
+ end
20
+
21
+ def properties
22
+ @properties
23
+ end
24
+ end
25
+ end
@@ -1,3 +1,3 @@
1
1
  module GirFFI
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.0"
3
3
  end
data/lib/gir_ffi-base.rb CHANGED
@@ -1,2 +1,5 @@
1
+ # This section contains code that is needed by GObjectIntrospection, but
2
+ # belongs in modules that can only be created fully once GObjectIntrospection
3
+ # is fully loaded.
1
4
  require 'gir_ffi-base/glib/strv'
2
5
  require 'gir_ffi-base/gobject/lib'
data/lib/gir_ffi.rb CHANGED
@@ -21,7 +21,8 @@ module GirFFI
21
21
  end
22
22
 
23
23
  def self.define_type klass, &block
24
- Builder::Type::UserDefined.new(klass, &block).build_class
24
+ info = UserDefinedTypeInfo.new(klass, &block)
25
+ Builder::Type::UserDefined.new(info).build_class
25
26
 
26
27
  klass.get_gtype
27
28
  end
@@ -0,0 +1,87 @@
1
+ require 'base_test_helper'
2
+
3
+ describe GLib::SizedArray do
4
+ describe "::wrap" do
5
+ it "takes a type, size and pointer and returns a GLib::SizedArray wrapping them" do
6
+ mock(ptr = Object.new).null? { false }
7
+ sarr = GLib::SizedArray.wrap :gint32, 3, ptr
8
+ assert_instance_of GLib::SizedArray, sarr
9
+ assert_equal ptr, sarr.to_ptr
10
+ assert_equal 3, sarr.size
11
+ assert_equal :gint32, sarr.element_type
12
+ end
13
+
14
+ it "returns nil if the wrapped pointer is null" do
15
+ mock(ptr = Object.new).null? { true }
16
+ sarr = GLib::SizedArray.wrap :gint32, 3, ptr
17
+ sarr.must_be_nil
18
+ end
19
+ end
20
+
21
+ describe "#each" do
22
+ it "yields each element" do
23
+ ary = ["one", "two", "three"]
24
+ ptrs = ary.map {|a| FFI::MemoryPointer.from_string(a)}
25
+ ptrs << nil
26
+ block = FFI::MemoryPointer.new(:pointer, ptrs.length)
27
+ block.write_array_of_pointer ptrs
28
+
29
+ sarr = GLib::SizedArray.new :utf8, 3, block
30
+ arr = []
31
+ sarr.each do |str|
32
+ arr << str
33
+ end
34
+ assert_equal ["one", "two", "three"], arr
35
+ end
36
+ end
37
+
38
+ describe "::from" do
39
+ context "from a Ruby array" do
40
+ it "creates a GLib::SizedArray with the same elements" do
41
+ arr = GLib::SizedArray.from :gint32, 3, [3, 2, 1]
42
+ arr.must_be_instance_of GLib::SizedArray
43
+ assert_equal [3, 2, 1], arr.to_a
44
+ end
45
+
46
+ it "raises an error if the array has the wrong number of elements" do
47
+ lambda { GLib::SizedArray.from :gint32, 4, [3, 2, 1] }.must_raise ArgumentError
48
+ end
49
+
50
+ it "uses the array's size if passed -1 as the size" do
51
+ arr = GLib::SizedArray.from :gint32, -1, [3, 2, 1]
52
+ arr.size.must_equal 3
53
+ end
54
+ end
55
+
56
+ context "from a GLib::SizedArray" do
57
+ it "return its argument" do
58
+ arr = GLib::SizedArray.from :gint32, 3, [3, 2, 1]
59
+ arr2 = GLib::SizedArray.from :gint32, 3, arr
60
+ assert_equal arr, arr2
61
+ end
62
+
63
+ it "raises an error if the argument has the wrong number of elements" do
64
+ arr = GLib::SizedArray.from :gint32, 3, [3, 2, 1]
65
+ lambda { GLib::SizedArray.from :gint32, 4, arr }.must_raise ArgumentError
66
+ end
67
+ end
68
+
69
+ it "returns nil when passed nil" do
70
+ arr = GLib::SizedArray.from :gint32, 0, nil
71
+ arr.must_be_nil
72
+ end
73
+
74
+ it "wraps its argument if given a pointer" do
75
+ arr = GLib::SizedArray.from :gint32, 3, [3, 2, 1]
76
+ arr2 = GLib::SizedArray.from :gint32, 3, arr.to_ptr
77
+ assert_instance_of GLib::SizedArray, arr2
78
+ refute_equal arr, arr2
79
+ assert_equal arr.to_a, arr2.to_a
80
+ end
81
+ end
82
+
83
+ it "includes Enumerable" do
84
+ GLib::SizedArray.must_include Enumerable
85
+ end
86
+ end
87
+
@@ -3,10 +3,6 @@ require 'introspection_test_helper'
3
3
  describe GObjectIntrospection::IBaseInfo do
4
4
  let(:described_class) { GObjectIntrospection::IBaseInfo }
5
5
  describe "#initialize" do
6
- it "raises an error if nil is passed" do
7
- proc { described_class.new nil }.must_raise ArgumentError
8
- end
9
-
10
6
  it "raises an error if a null pointer is passed" do
11
7
  mock(ptr = Object.new).null? { true }
12
8
  proc { described_class.new ptr }.must_raise ArgumentError
@@ -21,7 +17,10 @@ describe GObjectIntrospection::IBaseInfo do
21
17
 
22
18
  describe "upon garbage collection" do
23
19
  it "calls g_base_info_unref" do
24
- skip "cannot be reliably tested on JRuby" if RUBY_PLATFORM == 'java'
20
+ if defined?(RUBY_ENGINE) && ['jruby', 'rbx'].include?(RUBY_ENGINE)
21
+ skip "cannot be reliably tested on JRuby and Rubinius"
22
+ end
23
+
25
24
  mock(ptr = Object.new).null? { false }
26
25
  mock(lib = Object.new).g_base_info_unref(ptr) { nil }
27
26
  described_class.new ptr, lib