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