gir_ffi 0.9.4 → 0.9.5
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.
- checksums.yaml +4 -4
- data/Changelog.md +11 -0
- data/README.md +8 -6
- data/TODO.md +3 -0
- data/lib/ffi-glib.rb +2 -1
- data/lib/ffi-gobject.rb +2 -1
- data/lib/ffi-gobject/object.rb +19 -9
- data/lib/ffi-gobject/value.rb +15 -3
- data/lib/gir_ffi-base.rb +9 -4
- data/lib/gir_ffi-base/glib.rb +8 -0
- data/lib/gir_ffi-base/glib/boolean.rb +1 -0
- data/lib/gir_ffi-base/glib/strv.rb +1 -0
- data/lib/gir_ffi-base/gobject.rb +5 -1
- data/lib/gir_ffi/boxed_base.rb +12 -0
- data/lib/gir_ffi/builder.rb +10 -1
- data/lib/gir_ffi/builders/argument_builder.rb +8 -4
- data/lib/gir_ffi/builders/base_return_value_builder.rb +38 -0
- data/lib/gir_ffi/builders/callback_return_value_builder.rb +2 -30
- data/lib/gir_ffi/builders/initializer_return_value_builder.rb +2 -6
- data/lib/gir_ffi/builders/module_builder.rb +2 -3
- data/lib/gir_ffi/builders/property_argument_builder.rb +23 -0
- data/lib/gir_ffi/builders/property_builder.rb +65 -46
- data/lib/gir_ffi/builders/property_return_value_builder.rb +14 -0
- data/lib/gir_ffi/builders/return_value_builder.rb +9 -33
- data/lib/gir_ffi/callback_base.rb +5 -0
- data/lib/gir_ffi/core.rb +3 -3
- data/lib/gir_ffi/in_pointer.rb +1 -1
- data/lib/gir_ffi/info_ext/i_signal_info.rb +2 -3
- data/lib/gir_ffi/info_ext/i_type_info.rb +22 -14
- data/lib/gir_ffi/interface_base.rb +12 -0
- data/lib/gir_ffi/user_defined_type_info.rb +8 -0
- data/lib/gir_ffi/version.rb +1 -1
- data/test/gir_ffi/builders/function_builder_test.rb +19 -0
- data/test/gir_ffi/builders/object_builder_test.rb +5 -11
- data/test/gir_ffi/builders/property_builder_test.rb +37 -5
- data/test/gir_ffi/builders/signal_closure_builder_test.rb +21 -0
- data/test/gir_ffi/builders/vfunc_builder_test.rb +20 -0
- data/test/gir_ffi/info_ext/i_type_info_test.rb +18 -0
- data/test/gir_ffi/user_defined_type_info_test.rb +25 -0
- data/test/gir_ffi_test_helper.rb +2 -6
- data/test/integration/generated_gimarshallingtests_test.rb +5 -5
- data/test/integration/generated_gio_test.rb +2 -3
- data/test/integration/generated_gst_test.rb +1 -0
- data/test/integration/generated_regress_test.rb +630 -189
- data/test/integration/generated_utility_test.rb +173 -0
- data/test/lib/Makefile.am +3 -5
- metadata +7 -2
@@ -1,6 +1,63 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'gir_ffi/builders/method_template'
|
3
|
+
require 'gir_ffi/builders/argument_builder_collection'
|
4
|
+
require 'gir_ffi/builders/property_argument_builder'
|
5
|
+
require 'gir_ffi/builders/property_return_value_builder'
|
6
|
+
require 'gir_ffi/variable_name_generator'
|
7
|
+
require 'gir_ffi/field_argument_info'
|
8
|
+
|
2
9
|
module GirFFI
|
3
10
|
module Builders
|
11
|
+
# Method builder used for the creation of property getter methods.
|
12
|
+
class PropertyGetterBuilder
|
13
|
+
attr_reader :info
|
14
|
+
attr_reader :return_value_builder
|
15
|
+
|
16
|
+
def initialize(info, return_value_builder)
|
17
|
+
@return_value_builder = return_value_builder
|
18
|
+
@info = info
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_definition
|
22
|
+
template.method_definition
|
23
|
+
end
|
24
|
+
|
25
|
+
def template
|
26
|
+
@template ||= MethodTemplate.new(self, argument_builder_collection)
|
27
|
+
end
|
28
|
+
|
29
|
+
def singleton_method?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_name
|
34
|
+
info.getter_name
|
35
|
+
end
|
36
|
+
|
37
|
+
def method_arguments
|
38
|
+
[]
|
39
|
+
end
|
40
|
+
|
41
|
+
def preparation
|
42
|
+
[]
|
43
|
+
end
|
44
|
+
|
45
|
+
def invocation
|
46
|
+
"get_property('#{info.name}')"
|
47
|
+
end
|
48
|
+
|
49
|
+
def result
|
50
|
+
[return_value_builder.return_value_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def argument_builder_collection
|
56
|
+
@argument_builder_collection ||=
|
57
|
+
ArgumentBuilderCollection.new(return_value_builder, [])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
4
61
|
# Creates property getter and setter code for a given IPropertyInfo.
|
5
62
|
class PropertyBuilder
|
6
63
|
def initialize(property_info)
|
@@ -24,51 +81,20 @@ module GirFFI
|
|
24
81
|
container_class.class_eval setter_def
|
25
82
|
end
|
26
83
|
|
27
|
-
# TODO: Fix argument builders so converting_getter_def can always be used.
|
28
84
|
def getter_def
|
29
|
-
|
30
|
-
when :glist, :ghash
|
31
|
-
converting_getter_def
|
32
|
-
else
|
33
|
-
simple_getter_def
|
34
|
-
end
|
85
|
+
PropertyGetterBuilder.new(@info, getter_builder).method_definition
|
35
86
|
end
|
36
87
|
|
37
|
-
# TODO: Fix argument builders so converting_setter_def can always be used.
|
38
88
|
def setter_def
|
39
|
-
|
40
|
-
when :glist, :ghash, :strv
|
41
|
-
converting_setter_def
|
42
|
-
else
|
43
|
-
simple_setter_def
|
44
|
-
end
|
89
|
+
converting_setter_def
|
45
90
|
end
|
46
91
|
|
47
92
|
private
|
48
93
|
|
49
|
-
# TODO: Use a builder like MarshallingMethodBuilder
|
50
|
-
def converting_getter_def
|
51
|
-
capture = getter_builder.capture_variable_name
|
52
|
-
<<-CODE.reset_indentation
|
53
|
-
def #{getter_name}
|
54
|
-
#{capture} = get_property("#{property_name}")
|
55
|
-
#{getter_builder.post_conversion.join("\n")}
|
56
|
-
#{getter_builder.return_value_name}
|
57
|
-
end
|
58
|
-
CODE
|
59
|
-
end
|
60
|
-
|
61
|
-
def simple_getter_def
|
62
|
-
<<-CODE.reset_indentation
|
63
|
-
def #{getter_name}
|
64
|
-
get_property("#{property_name}")
|
65
|
-
end
|
66
|
-
CODE
|
67
|
-
end
|
68
|
-
|
69
94
|
def getter_builder
|
70
|
-
@getter_builder ||=
|
71
|
-
|
95
|
+
@getter_builder ||=
|
96
|
+
PropertyReturnValueBuilder.new(VariableNameGenerator.new,
|
97
|
+
argument_info)
|
72
98
|
end
|
73
99
|
|
74
100
|
def converting_setter_def
|
@@ -80,17 +106,10 @@ module GirFFI
|
|
80
106
|
CODE
|
81
107
|
end
|
82
108
|
|
83
|
-
def simple_setter_def
|
84
|
-
<<-CODE.reset_indentation
|
85
|
-
def #{setter_name} value
|
86
|
-
set_property("#{property_name}", value)
|
87
|
-
end
|
88
|
-
CODE
|
89
|
-
end
|
90
|
-
|
91
109
|
def setter_builder
|
92
|
-
@setter_builder ||=
|
93
|
-
|
110
|
+
@setter_builder ||=
|
111
|
+
PropertyArgumentBuilder.new(VariableNameGenerator.new,
|
112
|
+
argument_info)
|
94
113
|
end
|
95
114
|
|
96
115
|
def property_name
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'gir_ffi/builders/return_value_builder'
|
3
|
+
|
4
|
+
module GirFFI
|
5
|
+
module Builders
|
6
|
+
# Implements building post-processing statements for return values of
|
7
|
+
# property getters.
|
8
|
+
class PropertyReturnValueBuilder < ReturnValueBuilder
|
9
|
+
def needs_c_to_ruby_conversion?
|
10
|
+
type_info.needs_c_to_ruby_conversion_for_properties?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,32 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'gir_ffi/builders/
|
2
|
+
require 'gir_ffi/builders/base_return_value_builder'
|
3
3
|
require 'gir_ffi/builders/full_c_to_ruby_convertor'
|
4
4
|
require 'gir_ffi/builders/closure_convertor'
|
5
5
|
|
6
6
|
module GirFFI
|
7
7
|
module Builders
|
8
8
|
# Implements building post-processing statements for return values.
|
9
|
-
class ReturnValueBuilder <
|
10
|
-
def relevant?
|
11
|
-
!void_return_value? && !arginfo.skip?
|
12
|
-
end
|
13
|
-
|
14
|
-
def capture_variable_name
|
15
|
-
@capture_variable_name ||= new_variable if relevant?
|
16
|
-
end
|
17
|
-
|
18
|
-
def post_converted_name
|
19
|
-
@post_converted_name ||= if has_post_conversion?
|
20
|
-
new_variable
|
21
|
-
else
|
22
|
-
capture_variable_name
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def return_value_name
|
27
|
-
post_converted_name if has_return_value_name?
|
28
|
-
end
|
29
|
-
|
9
|
+
class ReturnValueBuilder < BaseReturnValueBuilder
|
30
10
|
def post_conversion
|
31
11
|
if has_post_conversion?
|
32
12
|
["#{post_converted_name} = #{post_convertor.conversion}"]
|
@@ -35,12 +15,16 @@ module GirFFI
|
|
35
15
|
end
|
36
16
|
end
|
37
17
|
|
38
|
-
private
|
39
|
-
|
40
18
|
def has_post_conversion?
|
41
|
-
closure? ||
|
19
|
+
closure? || needs_c_to_ruby_conversion?
|
20
|
+
end
|
21
|
+
|
22
|
+
def needs_c_to_ruby_conversion?
|
23
|
+
type_info.needs_c_to_ruby_conversion_for_functions?
|
42
24
|
end
|
43
25
|
|
26
|
+
private
|
27
|
+
|
44
28
|
def post_convertor
|
45
29
|
@post_convertor ||= if closure?
|
46
30
|
ClosureConvertor.new(capture_variable_name)
|
@@ -54,14 +38,6 @@ module GirFFI
|
|
54
38
|
def length_argument_name
|
55
39
|
length_arg && length_arg.post_converted_name
|
56
40
|
end
|
57
|
-
|
58
|
-
def void_return_value?
|
59
|
-
specialized_type_tag == :void && !type_info.pointer?
|
60
|
-
end
|
61
|
-
|
62
|
-
def has_return_value_name?
|
63
|
-
relevant? && !array_arg
|
64
|
-
end
|
65
41
|
end
|
66
42
|
end
|
67
43
|
end
|
@@ -13,6 +13,7 @@ module GirFFI
|
|
13
13
|
FFI::Type::POINTER
|
14
14
|
end
|
15
15
|
|
16
|
+
# TODO: Return instance of this class
|
16
17
|
def self.from_native(value, _context)
|
17
18
|
return nil if !value || value.null?
|
18
19
|
FFI::Function.new(gir_ffi_builder.return_ffi_type,
|
@@ -74,6 +75,10 @@ module GirFFI
|
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|
78
|
+
def to_ptr
|
79
|
+
to_native.to_ptr
|
80
|
+
end
|
81
|
+
|
77
82
|
def self.copy_value_to_pointer(value, pointer)
|
78
83
|
pointer.put_pointer 0, to_native(value, nil)
|
79
84
|
end
|
data/lib/gir_ffi/core.rb
CHANGED
@@ -23,9 +23,9 @@ require 'gir_ffi/version'
|
|
23
23
|
# Main module containing classes and modules needed for generating GLib and
|
24
24
|
# GObject bindings.
|
25
25
|
module GirFFI
|
26
|
-
def self.setup(
|
27
|
-
|
28
|
-
GirFFI::Builder.build_module
|
26
|
+
def self.setup(namespace, version = nil)
|
27
|
+
namespace = namespace.to_s
|
28
|
+
GirFFI::Builder.build_module namespace, version
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.define_type(klass, &block)
|
data/lib/gir_ffi/in_pointer.rb
CHANGED
@@ -16,9 +16,8 @@ module GirFFI
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def arguments_to_gvalues(instance, arguments)
|
19
|
-
arg_g_values = args.map
|
20
|
-
|
21
|
-
g_value.set_value arg
|
19
|
+
arg_g_values = args.zip(arguments).map do |info, arg|
|
20
|
+
info.argument_type.make_g_value.tap { |it| it.set_value arg }
|
22
21
|
end
|
23
22
|
|
24
23
|
arg_g_values.unshift GObject::Value.wrap_instance(instance)
|
@@ -7,24 +7,24 @@ module GirFFI
|
|
7
7
|
module ITypeInfo
|
8
8
|
def self.flattened_tag_to_gtype_map
|
9
9
|
@flattened_tag_to_gtype_map ||= {
|
10
|
-
array
|
11
|
-
c
|
12
|
-
gboolean
|
13
|
-
ghash
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
[:array, true] => GObject::TYPE_ARRAY,
|
11
|
+
[:c, true] => GObject::TYPE_POINTER,
|
12
|
+
[:gboolean, false] => GObject::TYPE_BOOLEAN,
|
13
|
+
[:ghash, true] => GObject::TYPE_HASH_TABLE,
|
14
|
+
[:glist, true] => GObject::TYPE_POINTER,
|
15
|
+
[:gint32, false] => GObject::TYPE_INT,
|
16
|
+
[:gint64, false] => GObject::TYPE_INT64,
|
17
|
+
[:guint64, false] => GObject::TYPE_UINT64,
|
18
|
+
[:strv, true] => GObject::TYPE_STRV,
|
19
|
+
[:utf8, true] => GObject::TYPE_STRING,
|
20
|
+
[:void, true] => GObject::TYPE_POINTER,
|
21
|
+
[:void, false] => GObject::TYPE_NONE
|
20
22
|
}.freeze
|
21
23
|
end
|
22
24
|
|
23
25
|
def gtype
|
24
26
|
return interface.gtype if tag == :interface
|
25
|
-
|
26
|
-
return type if type
|
27
|
-
raise "Can't find GType for #{flattened_tag} pointer? = #{pointer?}"
|
27
|
+
ITypeInfo.flattened_tag_to_gtype_map.fetch [flattened_tag, pointer?]
|
28
28
|
end
|
29
29
|
|
30
30
|
def make_g_value
|
@@ -158,13 +158,21 @@ module GirFFI
|
|
158
158
|
end
|
159
159
|
|
160
160
|
def needs_c_to_ruby_conversion_for_closures?
|
161
|
-
[:array, :c, :ghash, :struct, :strv].include?(flattened_tag)
|
161
|
+
[:array, :c, :ghash, :glist, :struct, :strv].include?(flattened_tag)
|
162
162
|
end
|
163
163
|
|
164
164
|
def needs_ruby_to_c_conversion_for_closures?
|
165
165
|
[:array].include?(flattened_tag)
|
166
166
|
end
|
167
167
|
|
168
|
+
def needs_ruby_to_c_conversion_for_properties?
|
169
|
+
[:glist, :ghash, :strv, :callback].include?(flattened_tag)
|
170
|
+
end
|
171
|
+
|
172
|
+
def needs_c_to_ruby_conversion_for_properties?
|
173
|
+
[:glist, :ghash, :callback].include?(flattened_tag)
|
174
|
+
end
|
175
|
+
|
168
176
|
def extra_conversion_arguments
|
169
177
|
case flattened_tag
|
170
178
|
when :utf8, :void
|
@@ -6,10 +6,22 @@ module GirFFI
|
|
6
6
|
module InterfaceBase
|
7
7
|
include RegisteredTypeBase
|
8
8
|
|
9
|
+
def setup_and_call(method, arguments, &block)
|
10
|
+
method_name = setup_method method.to_s
|
11
|
+
unless method_name
|
12
|
+
raise NoMethodError, "undefined method `#{method}' for #{self}"
|
13
|
+
end
|
14
|
+
send method_name, *arguments, &block
|
15
|
+
end
|
16
|
+
|
9
17
|
def setup_instance_method(name)
|
10
18
|
gir_ffi_builder.setup_instance_method name
|
11
19
|
end
|
12
20
|
|
21
|
+
def setup_method(name)
|
22
|
+
gir_ffi_builder.setup_method name
|
23
|
+
end
|
24
|
+
|
13
25
|
def wrap(ptr)
|
14
26
|
ptr.to_object
|
15
27
|
end
|
data/lib/gir_ffi/version.rb
CHANGED
@@ -36,6 +36,25 @@ describe GirFFI::Builders::FunctionBuilder do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
describe 'for methods taking a zero-terminated array with length argument' do
|
40
|
+
let(:function_info) { get_method_introspection_data 'Regress', 'AnnotationObject', 'parse_args' }
|
41
|
+
it 'builds a correct definition' do
|
42
|
+
skip unless function_info
|
43
|
+
code.must_equal <<-CODE.reset_indentation
|
44
|
+
def parse_args(argv)
|
45
|
+
argc = argv.nil? ? 0 : argv.length
|
46
|
+
_v1 = GirFFI::InOutPointer.for :gint32
|
47
|
+
_v1.set_value argc
|
48
|
+
_v2 = GirFFI::InOutPointer.for [:pointer, :strv]
|
49
|
+
_v2.set_value GLib::Strv.from(argv)
|
50
|
+
Regress::Lib.regress_annotation_object_parse_args self, _v1, _v2
|
51
|
+
_v3 = GLib::Strv.wrap(_v2.to_value)
|
52
|
+
return _v3
|
53
|
+
end
|
54
|
+
CODE
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
39
58
|
describe 'for functions with callbacks' do
|
40
59
|
let(:function_info) { get_introspection_data 'Regress', 'test_callback_destroy_notify' }
|
41
60
|
it 'builds a correct definition' do
|
@@ -65,21 +65,15 @@ describe GirFFI::Builders::ObjectBuilder do
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
# TODO: Improve this spec to use less mocking
|
69
68
|
describe 'for a struct without defined fields' do
|
70
|
-
|
71
|
-
@gir = GObjectIntrospection::IRepository.default
|
72
|
-
@gir.require 'GObject', nil
|
69
|
+
let(:info) { get_introspection_data 'GObject', 'Binding' }
|
73
70
|
|
74
|
-
|
75
|
-
|
76
|
-
allow(info).to receive(:info_type).and_return :object
|
77
|
-
allow(info).to receive(:safe_name).and_return 'Bar'
|
78
|
-
allow(info).to receive(:namespace).and_return 'Foo'
|
71
|
+
it 'uses a single field of the parent struct type as the default layout' do
|
72
|
+
info.n_fields.must_equal 0
|
79
73
|
|
80
|
-
|
74
|
+
builder = GirFFI::Builders::ObjectBuilder.new info
|
81
75
|
|
82
|
-
spec =
|
76
|
+
spec = builder.send :layout_specification
|
83
77
|
assert_equal [:parent, GObject::Object::Struct, 0], spec
|
84
78
|
end
|
85
79
|
end
|
@@ -9,7 +9,7 @@ describe GirFFI::Builders::PropertyBuilder do
|
|
9
9
|
it 'generates the correct getter definition' do
|
10
10
|
expected = <<-CODE.reset_indentation
|
11
11
|
def list
|
12
|
-
_v1 = get_property(
|
12
|
+
_v1 = get_property('list')
|
13
13
|
_v2 = GLib::List.wrap(:utf8, _v1)
|
14
14
|
_v2
|
15
15
|
end
|
@@ -35,7 +35,7 @@ describe GirFFI::Builders::PropertyBuilder do
|
|
35
35
|
it 'generates the correct getter definition' do
|
36
36
|
expected = <<-CODE.reset_indentation
|
37
37
|
def hash_table
|
38
|
-
_v1 = get_property(
|
38
|
+
_v1 = get_property('hash-table')
|
39
39
|
_v2 = GLib::HashTable.wrap([:utf8, :gint8], _v1)
|
40
40
|
_v2
|
41
41
|
end
|
@@ -69,7 +69,8 @@ describe GirFFI::Builders::PropertyBuilder do
|
|
69
69
|
it 'generates the correct getter definition' do
|
70
70
|
expected = <<-CODE.reset_indentation
|
71
71
|
def some_strv
|
72
|
-
get_property(
|
72
|
+
_v1 = get_property('some-strv')
|
73
|
+
_v1
|
73
74
|
end
|
74
75
|
CODE
|
75
76
|
|
@@ -93,7 +94,8 @@ describe GirFFI::Builders::PropertyBuilder do
|
|
93
94
|
it 'generates the correct getter definition' do
|
94
95
|
expected = <<-CODE.reset_indentation
|
95
96
|
def string
|
96
|
-
get_property(
|
97
|
+
_v1 = get_property('string')
|
98
|
+
_v1
|
97
99
|
end
|
98
100
|
CODE
|
99
101
|
|
@@ -103,7 +105,37 @@ describe GirFFI::Builders::PropertyBuilder do
|
|
103
105
|
it 'generates the correct setter definition' do
|
104
106
|
expected = <<-CODE.reset_indentation
|
105
107
|
def string= value
|
106
|
-
|
108
|
+
_v1 = value
|
109
|
+
set_property("string", _v1)
|
110
|
+
end
|
111
|
+
CODE
|
112
|
+
|
113
|
+
builder.setter_def.must_equal expected
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe 'for a property of a callback type' do
|
118
|
+
let(:property_info) do
|
119
|
+
get_property_introspection_data('Regress', 'AnnotationObject', 'function-property')
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'generates the correct getter definition' do
|
123
|
+
expected = <<-CODE.reset_indentation
|
124
|
+
def function_property
|
125
|
+
_v1 = get_property('function-property')
|
126
|
+
_v2 = Regress::AnnotationCallback.wrap(_v1)
|
127
|
+
_v2
|
128
|
+
end
|
129
|
+
CODE
|
130
|
+
|
131
|
+
builder.getter_def.must_equal expected
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'generates the correct setter definition' do
|
135
|
+
expected = <<-CODE.reset_indentation
|
136
|
+
def function_property= value
|
137
|
+
_v1 = Regress::AnnotationCallback.from(value)
|
138
|
+
set_property("function-property", _v1)
|
107
139
|
end
|
108
140
|
CODE
|
109
141
|
|