gir_ffi 0.2.2 → 0.2.3

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 (69) hide show
  1. data/History.txt +6 -0
  2. data/lib/ffi-glib.rb +1 -0
  3. data/lib/ffi-glib/array.rb +49 -10
  4. data/lib/ffi-glib/hash_table.rb +19 -5
  5. data/lib/ffi-glib/list.rb +4 -1
  6. data/lib/ffi-glib/list_methods.rb +8 -1
  7. data/lib/ffi-glib/s_list.rb +4 -1
  8. data/lib/ffi-glib/strv.rb +31 -0
  9. data/lib/ffi-gobject.rb +2 -35
  10. data/lib/ffi-gobject/base.rb +38 -0
  11. data/lib/ffi-gobject/object.rb +28 -30
  12. data/lib/ffi-gobject/value.rb +72 -56
  13. data/lib/ffi-gobject_introspection/i_struct_info.rb +11 -1
  14. data/lib/ffi-gobject_introspection/lib.rb +3 -1
  15. data/lib/gir_ffi/arg_helper.rb +2 -19
  16. data/lib/gir_ffi/builder/argument.rb +239 -305
  17. data/lib/gir_ffi/builder/argument/base.rb +12 -9
  18. data/lib/gir_ffi/builder/argument/in_base.rb +2 -6
  19. data/lib/gir_ffi/builder/argument/in_out_base.rb +2 -5
  20. data/lib/gir_ffi/builder/argument/out_base.rb +0 -11
  21. data/lib/gir_ffi/builder/field.rb +55 -0
  22. data/lib/gir_ffi/builder/function.rb +7 -7
  23. data/lib/gir_ffi/builder/module.rb +5 -7
  24. data/lib/gir_ffi/builder/type/object.rb +0 -33
  25. data/lib/gir_ffi/builder/type/registered_type.rb +0 -16
  26. data/lib/gir_ffi/builder/type/struct_based.rb +3 -3
  27. data/lib/gir_ffi/builder/type/unintrospectable.rb +1 -1
  28. data/lib/gir_ffi/builder/type/with_layout.rb +26 -58
  29. data/lib/gir_ffi/builder/type/with_methods.rb +9 -11
  30. data/lib/gir_ffi/class_base.rb +24 -6
  31. data/lib/gir_ffi/ffi_ext/pointer.rb +15 -0
  32. data/lib/gir_ffi/in_pointer.rb +10 -5
  33. data/lib/gir_ffi/info_ext/i_field_info.rb +15 -0
  34. data/lib/gir_ffi/info_ext/i_type_info.rb +26 -0
  35. data/lib/gir_ffi/method_stubber.rb +18 -0
  36. data/lib/gir_ffi/type_map.rb +1 -0
  37. data/lib/gir_ffi/variable_name_generator.rb +2 -0
  38. data/lib/gir_ffi/version.rb +1 -1
  39. data/test/builder_test.rb +6 -5
  40. data/test/ffi-glib/array_test.rb +40 -5
  41. data/test/ffi-glib/hash_table_test.rb +27 -3
  42. data/test/ffi-glib/list_test.rb +23 -0
  43. data/test/ffi-glib/strv_test.rb +41 -0
  44. data/test/ffi-gobject/gobject_test.rb +26 -22
  45. data/test/ffi-gobject/value_test.rb +26 -1
  46. data/test/ffi-gobject_introspection/lib_test.rb +10 -0
  47. data/test/gir_ffi_test_helper.rb +1 -1
  48. data/test/integration/derived_classes_test.rb +31 -0
  49. data/test/integration/generated_gimarshallingtests_test.rb +29 -15
  50. data/test/integration/generated_gio_test.rb +5 -6
  51. data/test/integration/generated_regress_test.rb +11 -7
  52. data/test/integration/method_lookup_test.rb +32 -0
  53. data/test/interface_type_builder_test.rb +1 -1
  54. data/test/test_helper.rb +38 -0
  55. data/test/unit/argument_builder_test.rb +16 -4
  56. data/test/unit/class_base_test.rb +48 -0
  57. data/test/unit/function_builder_test.rb +144 -4
  58. data/test/unit/hash_table_element_type_provider_test.rb +16 -0
  59. data/test/unit/i_field_info_test.rb +39 -0
  60. data/test/unit/i_type_info_test.rb +23 -0
  61. data/test/unit/list_element_type_provider_test.rb +13 -0
  62. data/test/unit/module_builder_test.rb +1 -1
  63. data/test/unit/object_type_builder_test.rb +0 -17
  64. data/test/unit/struct_builder_test.rb +27 -39
  65. metadata +118 -60
  66. data/lib/gir_ffi/builder/argument/hash_table_base.rb +0 -20
  67. data/lib/gir_ffi/builder/argument/list_base.rb +0 -16
  68. data/test/class_base_test.rb +0 -10
  69. data/test/function_definition_builder_test.rb +0 -130
@@ -0,0 +1,48 @@
1
+ require File.expand_path('../gir_ffi_test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe GirFFI::ClassBase do
4
+ describe "a simple descendant" do
5
+ before do
6
+ @klass = Class.new GirFFI::ClassBase
7
+ end
8
+
9
+ it "has #from as a pass-through method" do
10
+ result = @klass.from :foo
11
+ result.must_equal :foo
12
+ end
13
+ end
14
+
15
+ describe "a descendant with multiple builders" do
16
+ it "looks up class methods in all builders" do
17
+ mock(builder = Object.new).setup_method("foo") { true }
18
+ klass = Class.new GirFFI::ClassBase
19
+ klass.const_set :GIR_FFI_BUILDER, builder
20
+
21
+ mock(sub_builder = Object.new).setup_method("foo") { false }
22
+ sub_klass = Class.new klass do
23
+ def self.foo; end
24
+ end
25
+ sub_klass.const_set :GIR_FFI_BUILDER, sub_builder
26
+
27
+ sub_klass.setup_and_call :foo
28
+ end
29
+
30
+ it "looks up class methods in all builders" do
31
+ mock(builder = Object.new).setup_instance_method("foo") { true }
32
+ klass = Class.new GirFFI::ClassBase
33
+ klass.const_set :GIR_FFI_BUILDER, builder
34
+
35
+ mock(sub_builder = Object.new).setup_instance_method("foo") { false }
36
+ sub_klass = Class.new klass do
37
+ def foo; end
38
+ def initialize; end
39
+ def self.new; self._real_new; end
40
+ end
41
+ sub_klass.const_set :GIR_FFI_BUILDER, sub_builder
42
+
43
+ obj = sub_klass.new
44
+
45
+ obj.setup_and_call :foo
46
+ end
47
+ end
48
+ end
@@ -13,13 +13,13 @@ describe GirFFI::Builder::Function do
13
13
 
14
14
  it "builds a correct definition of Regress:test_array_fixed_out_objects" do
15
15
  go = get_introspection_data 'Regress', 'test_array_fixed_out_objects'
16
- fbuilder = GirFFI::Builder::Function.new go, Lib
16
+ fbuilder = GirFFI::Builder::Function.new go, DummyLib
17
17
  code = fbuilder.generate
18
18
 
19
19
  expected = <<-CODE
20
- def test_array_fixed_out_objects
20
+ def self.test_array_fixed_out_objects
21
21
  _v1 = GirFFI::InOutPointer.for_array [:pointer, ::Regress::TestObj]
22
- ::Lib.regress_test_array_fixed_out_objects _v1
22
+ DummyLib.regress_test_array_fixed_out_objects _v1
23
23
  _v2 = _v1.to_sized_array_value 2
24
24
  return _v2
25
25
  end
@@ -28,8 +28,148 @@ describe GirFFI::Builder::Function do
28
28
  assert_equal expected.reset_indentation, code
29
29
  end
30
30
 
31
- end
31
+ it "builds a correct definition for functions having a linked length argument" do
32
+ go = get_introspection_data 'Regress', 'test_array_gint16_in'
33
+ fbuilder = GirFFI::Builder::Function.new go, DummyLib
34
+ code = fbuilder.generate
35
+
36
+ expected = <<-CODE
37
+ def self.test_array_gint16_in ints
38
+ n_ints = ints.nil? ? 0 : ints.length
39
+ _v1 = n_ints
40
+ _v2 = GirFFI::InPointer.from_array :gint16, ints
41
+ _v3 = DummyLib.regress_test_array_gint16_in _v1, _v2
42
+ return _v3
43
+ end
44
+ CODE
45
+
46
+ assert_equal expected.reset_indentation, code
47
+ end
32
48
 
49
+ it "builds a correct definition for functions with callbacks" do
50
+ go = get_introspection_data 'Regress', 'test_callback_destroy_notify'
51
+ fbuilder = GirFFI::Builder::Function.new go, DummyLib
52
+ code = fbuilder.generate
53
+
54
+ expected = <<-CODE
55
+ def self.test_callback_destroy_notify callback, user_data, notify
56
+ _v1 = GirFFI::CallbackHelper.wrap_in_callback_args_mapper \"Regress\", \"TestCallbackUserData\", callback
57
+ DummyLib::CALLBACKS << _v1
58
+ _v2 = GirFFI::ArgHelper.object_to_inptr user_data
59
+ _v3 = GirFFI::CallbackHelper.wrap_in_callback_args_mapper \"GLib\", \"DestroyNotify\", notify
60
+ DummyLib::CALLBACKS << _v3
61
+ _v4 = DummyLib.regress_test_callback_destroy_notify _v1, _v2, _v3
62
+ return _v4
63
+ end
64
+ CODE
33
65
 
66
+ assert_equal expected.reset_indentation, code
67
+ end
68
+
69
+ it "builds correct definition for constructors" do
70
+ go = get_method_introspection_data 'Regress', 'TestObj', 'new_from_file'
71
+ fbuilder = GirFFI::Builder::Function.new go, DummyLib
72
+ code = fbuilder.generate
34
73
 
74
+ expected = <<-CODE
75
+ def self.new_from_file x
76
+ _v1 = GirFFI::InPointer.from :utf8, x
77
+ _v2 = FFI::MemoryPointer.new(:pointer).write_pointer nil
78
+ _v3 = DummyLib.regress_test_obj_new_from_file _v1, _v2
79
+ GirFFI::ArgHelper.check_error(_v2)
80
+ _v4 = self.constructor_wrap(_v3)
81
+ return _v4
82
+ end
83
+ CODE
84
+
85
+ assert_equal expected.reset_indentation, code
86
+ end
87
+
88
+ it "creates a call to GObject::Value#from for functions that take a GValue" do
89
+ go = get_introspection_data 'GIMarshallingTests', 'gvalue_in'
90
+ fbuilder = GirFFI::Builder::Function.new go, DummyLib
91
+ code = fbuilder.generate
92
+
93
+ expected = <<-CODE
94
+ def self.gvalue_in value
95
+ _v1 = ::GObject::Value.from value
96
+ DummyLib.gi_marshalling_tests_gvalue_in _v1
97
+
98
+ end
99
+ CODE
100
+
101
+ assert_equal expected.reset_indentation, code
102
+ end
103
+
104
+ it "builds correct definition for functions with a nullable input array" do
105
+ go = get_introspection_data 'Regress', 'test_array_int_null_in'
106
+ fbuilder = GirFFI::Builder::Function.new go, DummyLib
107
+ code = fbuilder.generate
35
108
 
109
+ expected = <<-CODE
110
+ def self.test_array_int_null_in arr
111
+ _v1 = GirFFI::InPointer.from_array :gint32, arr
112
+ len = arr.nil? ? 0 : arr.length
113
+ _v2 = len
114
+ DummyLib.regress_test_array_int_null_in _v1, _v2
115
+
116
+ end
117
+ CODE
118
+
119
+ assert_equal expected.reset_indentation, code
120
+ end
121
+
122
+ it "builds correct definition for functions with a nullable output array" do
123
+ go = get_introspection_data 'Regress', 'test_array_int_null_out'
124
+ fbuilder = GirFFI::Builder::Function.new go, DummyLib
125
+ code = fbuilder.generate
126
+
127
+ expected = <<-CODE
128
+ def self.test_array_int_null_out
129
+ _v1 = GirFFI::InOutPointer.for_array :gint32
130
+ _v2 = GirFFI::InOutPointer.for :gint32
131
+ DummyLib.regress_test_array_int_null_out _v1, _v2
132
+ _v3 = _v2.to_value
133
+ _v4 = _v1.to_sized_array_value _v3
134
+ return _v4
135
+ end
136
+ CODE
137
+
138
+ assert_equal expected.reset_indentation, code
139
+ end
140
+
141
+ it "builds the correct definition for a method with an inout array with size argument" do
142
+ go = get_method_introspection_data 'GIMarshallingTests', 'Object', 'method_array_inout'
143
+ fbuilder = GirFFI::Builder::Function.new go, DummyLib
144
+ code = fbuilder.generate
145
+
146
+ expected = <<-CODE
147
+ def method_array_inout ints
148
+ _v1 = GirFFI::InOutPointer.from_array :gint32, ints
149
+ length = ints.length
150
+ _v2 = GirFFI::InOutPointer.from :gint32, length
151
+ DummyLib.gi_marshalling_tests_object_method_array_inout self, _v1, _v2
152
+ _v3 = _v2.to_value
153
+ _v4 = _v1.to_sized_array_value _v3
154
+ return _v4
155
+ end
156
+ CODE
157
+
158
+ assert_equal expected.reset_indentation, code
159
+ end
160
+
161
+ it "builds a correct definition for a simple method" do
162
+ go = get_method_introspection_data 'Gtk', 'Widget', 'show'
163
+ fbuilder = GirFFI::Builder::Function.new go, DummyLib
164
+ code = fbuilder.generate
165
+
166
+ expected = <<-CODE
167
+ def show
168
+ DummyLib.gtk_widget_show self
169
+
170
+ end
171
+ CODE
172
+
173
+ assert_equal expected.reset_indentation, code
174
+ end
175
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path('../gir_ffi_test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe GirFFI::Builder::HashTableElementTypeProvider do
4
+ describe "#elm_t" do
5
+ it "returns a string with an array of the first two subtype tags" do
6
+ builder = Object.new
7
+ builder.extend GirFFI::Builder::HashTableElementTypeProvider
8
+
9
+ stub(builder).subtype_tag(0) { :foo }
10
+ stub(builder).subtype_tag(1) { :bar }
11
+
12
+ assert_equal "[:foo, :bar]", builder.elm_t
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,39 @@
1
+ require File.expand_path('../gir_ffi_test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe GirFFI::InfoExt::IFieldInfo do
4
+ describe "#layout_specification" do
5
+ it "returns an array of name, typespec and offset" do
6
+ testclass = Class.new do
7
+ include GirFFI::InfoExt::IFieldInfo
8
+ end
9
+
10
+ mock(type = Object.new).layout_specification_type { :bar }
11
+
12
+ field = testclass.new
13
+ mock(field).name { "foo" }
14
+ mock(field).field_type { type }
15
+ mock(field).offset { 0 }
16
+
17
+ result = field.layout_specification
18
+
19
+ assert_equal [:foo, :bar, 0], result
20
+ end
21
+
22
+ it "keeps a complex typespec intact" do
23
+ testclass = Class.new do
24
+ include GirFFI::InfoExt::IFieldInfo
25
+ end
26
+
27
+ mock(type = Object.new).layout_specification_type { [:bar, 2] }
28
+
29
+ field = testclass.new
30
+ mock(field).name { "foo" }
31
+ mock(field).field_type { type }
32
+ mock(field).offset { 0 }
33
+
34
+ result = field.layout_specification
35
+
36
+ assert_equal [:foo, [:bar, 2], 0], result
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../gir_ffi_test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe GirFFI::InfoExt::ITypeInfo do
4
+ describe "#layout_specification_type" do
5
+ it "returns an array with elements subtype and size for type :array" do
6
+ testclass = Class.new do
7
+ include GirFFI::InfoExt::ITypeInfo
8
+ end
9
+
10
+ mock(subtype = Object.new).layout_specification_type { :foo }
11
+
12
+ type = testclass.new
13
+ mock(type).array_fixed_size { 2 }
14
+ mock(type).param_type(0) { subtype }
15
+
16
+ mock(GirFFI::Builder).itypeinfo_to_ffitype(type) { :array }
17
+
18
+ result = type.layout_specification_type
19
+
20
+ assert_equal [:foo, 2], result
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path('../gir_ffi_test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe GirFFI::Builder::ListElementTypeProvider do
4
+ describe "#elm_t" do
5
+ it "returns a string with just the first subtype tag" do
6
+ builder = Object.new
7
+ builder.extend GirFFI::Builder::ListElementTypeProvider
8
+ mock(builder).subtype_tag { :foo }
9
+
10
+ assert_equal ":foo", builder.elm_t
11
+ end
12
+ end
13
+ end
@@ -54,7 +54,7 @@ describe GirFFI::Builder::Module do
54
54
  describe "for a :function argument" do
55
55
  it "creates a GirFFI::Builder::Function object" do
56
56
  builder = GirFFI::Builder::Module.new "Foo"
57
- mock(builder).libmodule { Lib }
57
+ mock(builder).libmodule { DummyLib }
58
58
 
59
59
  stub(info = Object.new).info_type { :function }
60
60
 
@@ -1,23 +1,6 @@
1
1
  require File.expand_path('../gir_ffi_test_helper.rb', File.dirname(__FILE__))
2
2
 
3
3
  describe GirFFI::Builder::Type::Object do
4
- before do
5
- GirFFI.setup :Regress
6
- end
7
-
8
- describe "#setup_method" do
9
- it "sets up singleton methods defined in a class's parent" do
10
- info = get_introspection_data 'Regress', 'TestSubObj'
11
- assert_nil info.find_method "static_method"
12
- parent = info.parent
13
- assert_not_nil parent.find_method "static_method"
14
-
15
- b = GirFFI::Builder::Type::Object.new(info)
16
- b.setup_method "static_method"
17
- pass
18
- end
19
- end
20
-
21
4
  describe "#find_property" do
22
5
  it "finds a property specified on the class itself" do
23
6
  builder = GirFFI::Builder::Type::Object.new(
@@ -1,5 +1,6 @@
1
1
  require File.expand_path('../gir_ffi_test_helper.rb', File.dirname(__FILE__))
2
2
 
3
+ # FIXME: Test WithLayout directly, rather than through Struct.
3
4
  describe GirFFI::Builder::Type::Struct do
4
5
  describe "#pretty_print" do
5
6
  describe "for a struct with no methods" do
@@ -16,7 +17,7 @@ describe GirFFI::Builder::Type::Struct do
16
17
 
17
18
  describe "for a struct with a method" do
18
19
  it "returns a class block with the pretty printed method inside" do
19
- # FIXME: Loads of mocks. Make info objects create their own builders.
20
+ # FIXME: Loads of mocks.
20
21
 
21
22
  # Function info and its builder
22
23
  stub(func_info = Object.new).info_type { :function }
@@ -42,28 +43,34 @@ describe GirFFI::Builder::Type::Struct do
42
43
 
43
44
  describe "for a struct with a simple layout" do
44
45
  before do
45
- stub(@type = Object.new).pointer? { false }
46
- stub(@type).tag { :gint32 }
46
+ @field = Object.new
47
47
 
48
- stub(field = Object.new).field_type { @type }
49
- stub(field).name { "bar" }
50
- stub(field).offset { 0 }
51
- stub(field).writable? { true }
52
-
53
- stub(@struct = Object.new).safe_name { 'Bar' }
48
+ @struct = Object.new
49
+ stub(@struct).safe_name { 'Bar' }
54
50
  stub(@struct).namespace { 'Foo' }
55
- stub(@struct).fields { [ field ] }
56
- stub(@struct).find_method { }
51
+ stub(@struct).fields { [ @field ] }
57
52
 
58
53
  @builder = GirFFI::Builder::Type::Struct.new @struct
59
54
  end
60
55
 
61
56
  it "creates the correct layout specification" do
57
+ mock(@field).layout_specification { [:bar, :int32, 0] }
62
58
  spec = @builder.send :layout_specification
63
59
  assert_equal [:bar, :int32, 0], spec
64
60
  end
65
61
 
66
62
  it "creates getter and setter methods" do
63
+ # FIXME: Loads of stubs.
64
+
65
+ stub(type = Object.new).pointer? { false }
66
+ stub(type).tag { :gint32 }
67
+
68
+ stub(@field).field_type { type }
69
+ stub(@field).name { "bar" }
70
+ stub(@field).writable? { true }
71
+
72
+ stub(@struct).find_method { }
73
+
67
74
  m = Module.new { module Lib; end }
68
75
  stub(GirFFI::Builder).build_module('Foo') { m }
69
76
 
@@ -80,35 +87,18 @@ describe GirFFI::Builder::Type::Struct do
80
87
  end
81
88
  end
82
89
 
83
- describe "for a struct with a layout with a fixed-length array" do
84
- before do
85
- stub(subtype = Object.new).pointer? { false }
86
- stub(subtype).tag { :foo }
87
-
88
- stub(@type = Object.new).pointer? { false }
89
- stub(@type).tag { :array }
90
- stub(@type).array_fixed_size { 2 }
91
- stub(@type).param_type { subtype }
90
+ describe "for a struct with a layout with a complex type" do
91
+ it "does not flatten the complex type specification" do
92
+ mock(simplefield = Object.new).layout_specification { [:bar, :foo, 0] }
93
+ mock(complexfield = Object.new).layout_specification { [:baz, [:qux, 2], 0] }
94
+ mock(struct = Object.new).fields { [ simplefield, complexfield ] }
92
95
 
93
- stub(field = Object.new).field_type { @type }
94
- stub(field).name { "bar" }
95
- stub(field).offset { 0 }
96
+ stub(struct).safe_name { 'Bar' }
97
+ stub(struct).namespace { 'Foo' }
96
98
 
97
- stub(@struct = Object.new).safe_name { 'Bar' }
98
- stub(@struct).namespace { 'Foo' }
99
- stub(@struct).fields { [ field ] }
100
- end
101
-
102
- it "creates the correct ffi type for the array" do
103
- builder = GirFFI::Builder::Type::Struct.new @struct
104
- spec = builder.send :itypeinfo_to_ffitype_for_struct, @type
105
- assert_equal [:foo, 2], spec
106
- end
107
-
108
- it "creates the correct layout specification" do
109
- builder = GirFFI::Builder::Type::Struct.new @struct
99
+ builder = GirFFI::Builder::Type::Struct.new struct
110
100
  spec = builder.send :layout_specification
111
- assert_equal [:bar, [:foo, 2], 0], spec
101
+ assert_equal [:bar, :foo, 0, :baz, [:qux, 2], 0], spec
112
102
  end
113
103
  end
114
104
 
@@ -130,5 +120,3 @@ describe GirFFI::Builder::Type::Struct do
130
120
  end
131
121
  end
132
122
  end
133
-
134
-