gir_ffi 0.6.5 → 0.6.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ == 0.6.6 / 2013-08-05
2
+
3
+ * Handle GArrays of booleans and structs
4
+ * Improve handling of gbooleans
5
+
1
6
  == 0.6.5 / 2013-08-03
2
7
 
3
8
  * Handle inline arrays of structs
data/TODO.rdoc CHANGED
@@ -34,10 +34,11 @@ hidden issues.
34
34
  (11:47:15 PM) ebassi: the rest is "nice to have"
35
35
  (11:47:37 PM) ebassi: oh, and probably GBinding - but that's just because I wrote it ;-)
36
36
 
37
- == Compatibility with all implementations.
37
+ == Use FFI::DataConverter to automatically convert GObject types
38
38
 
39
- GirFFI is incompatible with Rubinius, but this is due to Rubinius' FFI
40
- implementation lagging behind the others.
39
+ GirFFI now generates loads of Something.wrap(ptr) calls; Perhaps these can be
40
+ replace by implementing to_native and from_native in ClassBase and including
41
+ FFI::DataConverter.
41
42
 
42
43
  == See Also
43
44
 
@@ -20,26 +20,41 @@ module GLib
20
20
  end
21
21
  end
22
22
 
23
- def append_vals data
24
- bytes = GirFFI::InPointer.from_array element_type, data
25
- len = data.length
23
+ def append_vals ary
24
+ bytes = GirFFI::InPointer.from_array element_type, ary
25
+ len = ary.length
26
26
  Lib.g_array_append_vals(self, bytes, len)
27
27
  self
28
28
  end
29
29
 
30
30
  # Re-implementation of the g_array_index macro
31
31
  def index idx
32
- ptr = @struct[:data].get_pointer(idx * get_element_size)
33
- # FIXME: Does not work for class-like values of element_type.
34
- GirFFI::ArgHelper.cast_from_pointer(element_type, ptr)
32
+ # TODO: Check idx < length
33
+ ptr = GirFFI::InOutPointer.new element_type, data + idx * get_element_size
34
+ case element_type
35
+ when :utf8
36
+ GirFFI::ArgHelper.ptr_to_utf8 ptr.to_value
37
+ when Symbol
38
+ ptr.to_value
39
+ else
40
+ element_type.wrap ptr.to_value
41
+ end
35
42
  end
36
43
 
37
44
  def each
38
- @struct[:len].times.each do |idx|
45
+ length.times.each do |idx|
39
46
  yield index(idx)
40
47
  end
41
48
  end
42
49
 
50
+ def length
51
+ @struct[:len]
52
+ end
53
+
54
+ def data
55
+ @struct[:data]
56
+ end
57
+
43
58
  def get_element_size
44
59
  Lib.g_array_get_element_size self
45
60
  end
@@ -66,11 +81,8 @@ module GLib
66
81
 
67
82
  def self.calculated_element_size type
68
83
  ffi_type = GirFFI::TypeMap.type_specification_to_ffitype(type)
69
- if ffi_type.is_a? Symbol
70
- FFI.type_size(ffi_type)
71
- else
72
- ffi_type.size
73
- end
84
+ # FIXME: Smell. Make struct ffi_types into DataConvertor?
85
+ FFI.type_size(ffi_type) rescue ffi_type.size
74
86
  end
75
87
 
76
88
  def calculated_element_size
@@ -104,7 +104,7 @@ module GObject
104
104
 
105
105
  def for_g_type g_type
106
106
  return nil if g_type == TYPE_NONE
107
- self.new.init g_type
107
+ self.new.tap {|it| it.init g_type }
108
108
  end
109
109
  end
110
110
 
@@ -1,5 +1,6 @@
1
1
  # This section contains code that is needed by GObjectIntrospection, but
2
2
  # belongs in modules that can only be created fully once GObjectIntrospection
3
3
  # is fully loaded.
4
+ require 'gir_ffi-base/glib/boolean'
4
5
  require 'gir_ffi-base/glib/strv'
5
6
  require 'gir_ffi-base/gobject/lib'
@@ -0,0 +1,17 @@
1
+ require 'ffi'
2
+
3
+ module GLib
4
+ # Implementation of gboolean
5
+ class Boolean
6
+ extend FFI::DataConverter
7
+ native_type :int #FFI::Type::INT
8
+
9
+ def self.from_native value, context
10
+ value != 0 ? true : false
11
+ end
12
+
13
+ def self.to_native value, context
14
+ value ? 1 : 0
15
+ end
16
+ end
17
+ end
@@ -1,12 +1,13 @@
1
1
  require 'ffi'
2
2
 
3
+ require 'gir_ffi-base'
4
+
5
+ require 'ffi-gobject_introspection'
6
+
3
7
  require 'gir_ffi/ffi_ext'
4
8
  require 'gir_ffi/class_base'
5
9
  require 'gir_ffi/type_map'
6
-
7
- require 'ffi-gobject_introspection'
8
10
  require 'gir_ffi/info_ext'
9
-
10
11
  require 'gir_ffi/in_pointer'
11
12
  require 'gir_ffi/in_out_pointer'
12
13
  require 'gir_ffi/zero_terminated'
@@ -13,18 +13,6 @@ module GirFFI
13
13
  # TODO: Move implementation here.
14
14
  ArgHelper.object_pointer_to_object self
15
15
  end
16
-
17
- # XXX: int32 is size 4, bool is size 1. Why u no crash?
18
- def put_bool offset, value
19
- int = value ? 1 : 0
20
- put_int32 offset, int
21
- end
22
-
23
- # XXX: int32 is size 4, bool is size 1. Why u no crash?
24
- def get_bool offset
25
- int = get_int32 offset
26
- return (int != 0)
27
- end
28
16
  end
29
17
  end
30
18
  end
@@ -1,36 +1,70 @@
1
1
  module GirFFI
2
2
  # The InOutPointer class handles conversion between ruby types and
3
3
  # pointers for arguments with direction :inout and :out.
4
+ #
5
+ # TODO: This has now become a more general extende pointer class and should be renamed.
4
6
  class InOutPointer < FFI::Pointer
5
7
  attr_reader :value_type
6
8
 
7
- def initialize value, type
8
- @ffi_type = TypeMap.type_specification_to_ffitype type
9
+ def initialize type, ptr = nil
9
10
  @value_type = type
10
11
 
11
- value = adjust_value_in value
12
-
13
- ptr = AllocationHelper.safe_malloc(FFI.type_size @ffi_type)
14
- ptr.send "put_#{@ffi_type}", 0, value
15
-
12
+ ptr ||= AllocationHelper.safe_malloc(value_type_size)
16
13
  super ptr
17
14
  end
18
15
 
19
16
  private :initialize
20
17
 
18
+ # TODO: Rename to get_value
21
19
  def to_value
22
- self.send "get_#{@ffi_type}", 0
20
+ case value_ffi_type
21
+ when Class
22
+ to_ptr
23
+ when Symbol
24
+ adjust_value_out self.send("get_#{value_ffi_type}", 0)
25
+ else
26
+ raise NotImplementedError
27
+ end
23
28
  end
24
29
 
25
- def self.for type
26
- if Array === type
27
- return self.new nil, *type
30
+ def set_value value
31
+ value = adjust_value_in value
32
+ case value_ffi_type
33
+ when Class
34
+ self.put_bytes 0, value.to_ptr.read_bytes(value_type_size), 0, value_type_size
35
+ when Symbol
36
+ self.send "put_#{value_ffi_type}", 0, value
37
+ else
38
+ raise NotImplementedError
28
39
  end
29
- self.new nil, type
40
+ end
41
+
42
+ def value_ffi_type
43
+ @value_ffi_type ||= case value_type
44
+ when :gboolean
45
+ :int
46
+ else
47
+ TypeMap.type_specification_to_ffitype value_type
48
+ end
49
+ end
50
+
51
+ def value_type_size
52
+ @value_type_size ||= case value_ffi_type
53
+ when Class
54
+ value_ffi_type.size
55
+ when Symbol
56
+ FFI.type_size value_ffi_type
57
+ else
58
+ raise NotImplementedError
59
+ end
60
+ end
61
+
62
+ def self.for type
63
+ self.new(type).tap {|ptr| ptr.set_value nil}
30
64
  end
31
65
 
32
66
  def self.from type, value
33
- self.new value, type
67
+ self.new(type).tap {|ptr| ptr.set_value value}
34
68
  end
35
69
 
36
70
  private
@@ -38,14 +72,23 @@ module GirFFI
38
72
  def adjust_value_in value
39
73
  case @value_type
40
74
  when :gboolean
41
- value
75
+ value ? 1 : 0
42
76
  else
43
77
  value || nil_value
44
78
  end
45
79
  end
46
80
 
81
+ def adjust_value_out value
82
+ case value_type
83
+ when :gboolean
84
+ value != 0
85
+ else
86
+ value
87
+ end
88
+ end
89
+
47
90
  def nil_value
48
- @ffi_type == :pointer ? nil : 0
91
+ value_ffi_type == :pointer ? nil : 0
49
92
  end
50
93
  end
51
94
  end
@@ -8,6 +8,8 @@ module GirFFI
8
8
  case type
9
9
  when :utf8, :filename
10
10
  from_utf8_array ary
11
+ when :gboolean
12
+ from_boolean_array ary
11
13
  when Symbol
12
14
  from_basic_type_array type, ary
13
15
  when Class
@@ -47,6 +49,10 @@ module GirFFI
47
49
  from_basic_type_array :pointer, ptr_ary
48
50
  end
49
51
 
52
+ def from_boolean_array ary
53
+ from_basic_type_array :int, ary.map {|val| val ? 1 : 0}
54
+ end
55
+
50
56
  def from_interface_pointer_array ary
51
57
  ptr_ary = ary.map {|ifc| ifc.to_ptr}
52
58
  ptr_ary << nil
@@ -65,6 +65,15 @@ module GirFFI
65
65
  end
66
66
  types.unshift(:pointer).push(:pointer)
67
67
  end
68
+
69
+ def return_ffi_type
70
+ result = super
71
+ if result == GLib::Boolean
72
+ :bool
73
+ else
74
+ result
75
+ end
76
+ end
68
77
  end
69
78
  end
70
79
  end
@@ -18,7 +18,7 @@ module GirFFI
18
18
  :array => :pointer,
19
19
  :utf8 => :pointer,
20
20
  :GType => gtype_type,
21
- :gboolean => :bool,
21
+ :gboolean => GLib::Boolean,
22
22
  :gunichar => :uint32,
23
23
  :gint8 => :int8,
24
24
  :guint8 => :uint8,
@@ -1,3 +1,3 @@
1
1
  module GirFFI
2
- VERSION = "0.6.5"
2
+ VERSION = "0.6.6"
3
3
  end
@@ -67,10 +67,15 @@ describe GLib::Array do
67
67
  assert_equal [1, 2, 3], arr.to_a
68
68
  end
69
69
 
70
- describe "::from" do
71
- it "creates a GArray from a Ruby array" do
70
+ describe ".from" do
71
+ it "creates a GArray from an array of :gint32" do
72
72
  arr = GLib::Array.from :gint32, [3, 2, 1]
73
- assert_equal [3, 2, 1], arr.to_a
73
+ arr.data.read_array_of_int32(3).must_equal [3, 2, 1]
74
+ end
75
+
76
+ it "creates a GArray from an array of :gboolean" do
77
+ arr = GLib::Array.from :gboolean, [true, false, true]
78
+ arr.data.read_array_of_int(3).must_equal [1, 0, 1]
74
79
  end
75
80
 
76
81
  it "return its argument if given a GArray" do
@@ -119,5 +124,27 @@ describe GLib::Array do
119
124
  arr.wont_be :==, other
120
125
  end
121
126
  end
122
- end
123
127
 
128
+ describe "#index" do
129
+ it "returns the proper element for an array of :gint32" do
130
+ arr = GLib::Array.from :gint32, [1, 2, 3]
131
+ arr.index(2).must_equal 3
132
+ end
133
+
134
+ it "returns the proper element for an array of :utf8" do
135
+ arr = GLib::Array.from :utf8, ["a", "b", "c"]
136
+ arr.index(1).must_equal "b"
137
+ end
138
+
139
+ it "returns the proper element for an array of :gboolean" do
140
+ arr = GLib::Array.from :gboolean, [true, false, true]
141
+ arr.index(1).must_equal false
142
+ end
143
+
144
+ it "returns the proper element for an array of struct" do
145
+ vals = [1, 2, 3].map {|i| GObject::EnumValue.new.tap {|ev| ev.value = i} }
146
+ arr = GLib::Array.from GObject::EnumValue, vals
147
+ arr.index(1).value.must_equal 2
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,27 @@
1
+ require 'gir_ffi_test_helper'
2
+
3
+ describe GLib::Boolean do
4
+ it "has the same native size as an int" do
5
+ FFI.type_size(GLib::Boolean).must_equal FFI.type_size :int
6
+ end
7
+
8
+ describe ".from_native" do
9
+ it "converts 0 to false" do
10
+ GLib::Boolean.from_native(0, "whatever").must_equal false
11
+ end
12
+
13
+ it "converts 1 to true" do
14
+ GLib::Boolean.from_native(1, "whatever").must_equal true
15
+ end
16
+ end
17
+
18
+ describe ".to_native" do
19
+ it "converts false to 0" do
20
+ GLib::Boolean.to_native(false, "whatever").must_equal 0
21
+ end
22
+
23
+ it "converts true to 1" do
24
+ GLib::Boolean.to_native(true, "whatever").must_equal 1
25
+ end
26
+ end
27
+ end
@@ -3,6 +3,15 @@ require 'gir_ffi_test_helper'
3
3
  require 'gir_ffi/in_out_pointer'
4
4
 
5
5
  describe GirFFI::InOutPointer do
6
+ describe ".new" do
7
+ it "wraps an existing pointer and a type" do
8
+ ptr = GirFFI::AllocationHelper.safe_malloc(FFI.type_size(:int32))
9
+ ptr.put_int32 0, 42
10
+ instance = GirFFI::InOutPointer.new :gint32, ptr
11
+ instance.to_value.must_equal 42
12
+ end
13
+ end
14
+
6
15
  describe "an instance created with .from" do
7
16
  before do
8
17
  @result = GirFFI::InOutPointer.from :gint32, 23
@@ -18,8 +27,14 @@ describe GirFFI::InOutPointer do
18
27
  end
19
28
 
20
29
  describe ".from" do
21
- it "handles :gboolean" do
22
- GirFFI::InOutPointer.from :gboolean, false
30
+ it "handles :gboolean false" do
31
+ ptr = GirFFI::InOutPointer.from :gboolean, false
32
+ ptr.read_int.must_equal 0
33
+ end
34
+
35
+ it "handles :gboolean true" do
36
+ ptr = GirFFI::InOutPointer.from :gboolean, true
37
+ ptr.read_int.must_equal(1)
23
38
  end
24
39
 
25
40
  it "handles :utf8 pointers" do
@@ -42,7 +57,7 @@ describe GirFFI::InOutPointer do
42
57
  end
43
58
  end
44
59
 
45
- describe "::for" do
60
+ describe ".for" do
46
61
  it "handles :gboolean" do
47
62
  GirFFI::InOutPointer.for :gboolean
48
63
  end
@@ -61,12 +76,12 @@ describe GirFFI::InOutPointer do
61
76
  describe "for :gboolean values" do
62
77
  it "works when the value is false" do
63
78
  ptr = GirFFI::InOutPointer.from :gboolean, false
64
- assert_equal false, ptr.to_value
79
+ ptr.to_value.must_equal false
65
80
  end
66
81
 
67
82
  it "works when the value is true" do
68
83
  ptr = GirFFI::InOutPointer.from :gboolean, true
69
- assert_equal true, ptr.to_value
84
+ ptr.to_value.must_equal true
70
85
  end
71
86
  end
72
87
 
@@ -77,5 +92,22 @@ describe GirFFI::InOutPointer do
77
92
  assert_equal "Some value", ptr.to_value.read_string
78
93
  end
79
94
  end
95
+
96
+ describe "for struct values" do
97
+ it "returns a pointer to the held value" do
98
+ val = GObject::EnumValue.new
99
+ val.value = 3
100
+ ptr = GirFFI::InOutPointer.from GObject::EnumValue, val
101
+ result = ptr.to_value
102
+ GObject::EnumValue.wrap(result).value.must_equal 3
103
+ end
104
+ end
105
+ end
106
+
107
+ describe "#value_ffi_type" do
108
+ it "returns :int for the :gboolean value type" do
109
+ ptr = GirFFI::InOutPointer.from :gboolean, true
110
+ ptr.value_ffi_type.must_equal :int
111
+ end
80
112
  end
81
113
  end
@@ -2,6 +2,7 @@ require 'gir_ffi_test_helper'
2
2
 
3
3
  describe GirFFI::InfoExt::ISignalInfo do
4
4
  let(:klass) { Class.new do
5
+ include GirFFI::InfoExt::ICallableInfo
5
6
  include GirFFI::InfoExt::ISignalInfo
6
7
  end }
7
8
  let(:signal_info) { klass.new }
@@ -55,4 +56,15 @@ describe GirFFI::InfoExt::ISignalInfo do
55
56
  end
56
57
  end
57
58
  end
59
+
60
+ describe "#return_ffi_type" do
61
+ # FIXME: This is needed because callbacks are limited in the accepted
62
+ # types. This should be fixed in FFI.
63
+ it "returns :bool for the :gboolean type" do
64
+ stub(return_type_info = Object.new).to_ffitype { GLib::Boolean }
65
+ stub(signal_info).return_type { return_type_info }
66
+
67
+ signal_info.return_ffi_type.must_equal :bool
68
+ end
69
+ end
58
70
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gir_ffi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.6.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-03 00:00:00.000000000 Z
12
+ date: 2013-08-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
@@ -170,6 +170,7 @@ files:
170
170
  - lib/gir_ffi/function_builder.rb
171
171
  - lib/gir_ffi-base/gir_ffi/library.rb
172
172
  - lib/gir_ffi-base/gobject/lib.rb
173
+ - lib/gir_ffi-base/glib/boolean.rb
173
174
  - lib/gir_ffi-base/glib/strv.rb
174
175
  - lib/ffi-gobject/ruby_style.rb
175
176
  - lib/ffi-gobject/ruby_closure.rb
@@ -266,6 +267,7 @@ files:
266
267
  - test/gir_ffi/info_ext/i_field_info_test.rb
267
268
  - test/gir_ffi/info_ext/i_function_info_test.rb
268
269
  - test/gir_ffi/interface_base_test.rb
270
+ - test/gir_ffi-base/glib/boolean_test.rb
269
271
  - test/gir_ffi-base/glib/strv_test.rb
270
272
  - test/ffi-gobject/object_class_test.rb
271
273
  - test/ffi-gobject/object_test.rb
@@ -358,6 +360,7 @@ test_files:
358
360
  - test/ffi-gobject_introspection/i_repository_test.rb
359
361
  - test/ffi-gobject_introspection/lib_test.rb
360
362
  - test/ffi-gobject_test.rb
363
+ - test/gir_ffi-base/glib/boolean_test.rb
361
364
  - test/gir_ffi-base/glib/strv_test.rb
362
365
  - test/gir_ffi/arg_helper_test.rb
363
366
  - test/gir_ffi/argument_builder_test.rb