gir_ffi 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog.md +16 -0
- data/DESIGN.md +17 -15
- data/lib/ffi-glib/array.rb +4 -5
- data/lib/ffi-glib/byte_array.rb +2 -4
- data/lib/ffi-glib/bytes.rb +12 -2
- data/lib/ffi-glib/hash_table.rb +31 -31
- data/lib/ffi-glib/list_methods.rb +5 -15
- data/lib/ffi-glib/ptr_array.rb +3 -3
- data/lib/ffi-gobject/closure.rb +2 -0
- data/lib/ffi-gobject/ruby_closure.rb +13 -15
- data/lib/ffi-gobject/value.rb +33 -27
- data/lib/ffi-gobject.rb +5 -3
- data/lib/ffi-gobject_introspection/i_base_info.rb +2 -1
- data/lib/ffi-gobject_introspection/i_interface_info.rb +1 -1
- data/lib/ffi-gobject_introspection/i_object_info.rb +2 -2
- data/lib/ffi-gobject_introspection/i_struct_info.rb +1 -1
- data/lib/ffi-gobject_introspection/i_union_info.rb +1 -1
- data/lib/gir_ffi/boxed_base.rb +8 -6
- data/lib/gir_ffi/builders/boxed_builder.rb +0 -10
- data/lib/gir_ffi/builders/null_class_builder.rb +13 -0
- data/lib/gir_ffi/builders/user_defined_builder.rb +3 -3
- data/lib/gir_ffi/class_base.rb +10 -6
- data/lib/gir_ffi/in_out_pointer.rb +1 -5
- data/lib/gir_ffi/info_ext/i_registered_type_info.rb +4 -0
- data/lib/gir_ffi/user_defined_type_info.rb +4 -0
- data/lib/gir_ffi/version.rb +1 -1
- data/test/ffi-glib/ruby_closure_test.rb +1 -1
- data/test/ffi-gobject/value_test.rb +29 -0
- data/test/ffi-gobject_introspection/i_interface_info_test.rb +21 -0
- data/test/ffi-gobject_introspection/i_object_info_test.rb +15 -1
- data/test/ffi-gobject_introspection/i_struct_info_test.rb +21 -0
- data/test/ffi-gobject_introspection/i_union_info_test.rb +15 -0
- data/test/gir_ffi/class_base_test.rb +31 -6
- data/test/gir_ffi/in_out_pointer_test.rb +21 -2
- data/test/gir_ffi/user_defined_type_info_test.rb +9 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6121625e854dd754146516dab64b67c650155c67
|
4
|
+
data.tar.gz: e486edea5ebffe7146c68dca786796f94ac58945
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 170a26c6f8aecc34a77722a5525d8b1534491febdd244fff0a9c88aa298a357ee0914f1fc15393da52b306d2f295e7aaba0180f258a187e942433658e51262ae
|
7
|
+
data.tar.gz: afbed9ce4c8869f8e44b6c1bbb36d22192bf27e01720874d9e3632fd5dd4b59fcc5604e785c39ccf1c6b8e6fe084270d7efee54f992a70e36dc469fd93508031
|
data/Changelog.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.8.2 / 2015-10-10
|
4
|
+
|
5
|
+
* Use inherited constructor for boxed types
|
6
|
+
* Make InOutPointer work correctly for boxed types
|
7
|
+
* Make .for work with boxed types
|
8
|
+
* Make #set_value work with boxed types
|
9
|
+
* Make GObject::Value support nil type:
|
10
|
+
* Make .wrap_ruby_value(nil) work
|
11
|
+
* Make #set_value and #get_value work when the type is TYPE_INVALID
|
12
|
+
* Make .for_gtype work with TYPE_INVALID and TYPE_NONE
|
13
|
+
* Make .from(nil) return a GObject::Value instead of nil
|
14
|
+
* Make #set_ruby_value private
|
15
|
+
* Make GObject::Object.signal_emit work with gobject-introspection 1.46
|
16
|
+
* Replace or remove all custom .new methods
|
17
|
+
* Make setup_method and setup_instance_method handle symbol arguments
|
18
|
+
|
3
19
|
## 0.8.1 / 2015-10-04
|
4
20
|
|
5
21
|
* Handle struct array fields with related length fields
|
data/DESIGN.md
CHANGED
@@ -64,25 +64,27 @@ cannot bootstrap itself.
|
|
64
64
|
|
65
65
|
## Object initialization
|
66
66
|
|
67
|
-
|
67
|
+
Each constructor method is implemented in Ruby by a pair of new/initialize
|
68
|
+
methods. For example, a constructor `new_from_file` is implemented as a
|
69
|
+
combination of the singleton method `new_from_file` and the instance method
|
70
|
+
`initialize_from_file`. User-created subclasses override the appropriate
|
71
|
+
initializer method and must call super with the appropriate arguments.
|
68
72
|
|
69
|
-
|
70
|
-
|
71
|
-
* No aliasing of Ruby's new. Overriding is possible with super being called.
|
72
|
-
* #initialize should behave as expected. We may enforce use of super in Ruby
|
73
|
-
subclasses.
|
74
|
-
|
75
|
-
Schematic depiction of what happens (can happen):
|
73
|
+
Here is an example of the generated pair of methods:
|
76
74
|
|
77
75
|
```ruby
|
78
|
-
class
|
79
|
-
def self.
|
80
|
-
|
81
|
-
|
82
|
-
|
76
|
+
class Regress::TestObj
|
77
|
+
def self.new_from_file(*args)
|
78
|
+
obj = allocate
|
79
|
+
obj.__send__ :initialize_from_file, *args
|
80
|
+
obj
|
83
81
|
end
|
84
82
|
|
85
|
-
def
|
86
|
-
|
83
|
+
def initialize_from_file(x)
|
84
|
+
_v1 = GirFFI::InPointer.from(:utf8, x)
|
85
|
+
_v2 = FFI::MemoryPointer.new(:pointer).write_pointer nil
|
86
|
+
_v3 = Regress::Lib.regress_test_obj_new_from_file _v1, _v2
|
87
|
+
GirFFI::ArgHelper.check_error(_v2)
|
88
|
+
store_pointer(_v3)
|
87
89
|
end
|
88
90
|
end
|
data/lib/ffi-glib/array.rb
CHANGED
@@ -13,11 +13,10 @@ module GLib
|
|
13
13
|
|
14
14
|
attr_reader :element_type
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
ptr
|
20
|
-
wrap type, ptr
|
16
|
+
def initialize(type)
|
17
|
+
@element_type = type
|
18
|
+
ptr = Lib.g_array_new(0, 0, calculated_element_size)
|
19
|
+
store_pointer(ptr)
|
21
20
|
end
|
22
21
|
|
23
22
|
# @api private
|
data/lib/ffi-glib/byte_array.rb
CHANGED
data/lib/ffi-glib/bytes.rb
CHANGED
@@ -32,13 +32,23 @@ module GLib
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
# Why redefine new here? The class builder will only define the full
|
36
|
+
# version of 'new' on first call, causing both new and initialize to be
|
37
|
+
# defined. This overwrites the custom version of initialize below.
|
38
|
+
# TODO: Improve class builder so this trick is not needed.
|
35
39
|
class << self
|
36
40
|
undef new
|
37
41
|
end
|
38
42
|
|
39
|
-
def self.new(
|
43
|
+
def self.new(*args)
|
44
|
+
obj = allocate
|
45
|
+
obj.__send__ :initialize, *args
|
46
|
+
obj
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(arr)
|
40
50
|
data = GirFFI::SizedArray.from :guint8, arr.size, arr
|
41
|
-
|
51
|
+
store_pointer Lib.g_bytes_new data.to_ptr, data.size
|
42
52
|
end
|
43
53
|
|
44
54
|
private
|
data/lib/ffi-glib/hash_table.rb
CHANGED
@@ -11,11 +11,11 @@ module GLib
|
|
11
11
|
attr_reader :key_type
|
12
12
|
attr_reader :value_type
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
def initialize(key_type, value_type)
|
15
|
+
@key_type = key_type
|
16
|
+
@value_type = value_type
|
17
|
+
store_pointer Lib.g_hash_table_new(
|
18
|
+
hash_function_for_key_type, equality_function_for_key_type)
|
19
19
|
end
|
20
20
|
|
21
21
|
# @api private
|
@@ -27,32 +27,6 @@ module GLib
|
|
27
27
|
ghash
|
28
28
|
end
|
29
29
|
|
30
|
-
# @api private
|
31
|
-
def self.hash_function_for(keytype)
|
32
|
-
case keytype
|
33
|
-
when :utf8
|
34
|
-
FFI::Function.new(:uint,
|
35
|
-
[:pointer],
|
36
|
-
find_support_function('g_str_hash'))
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# @api private
|
41
|
-
def self.equality_function_for(keytype)
|
42
|
-
case keytype
|
43
|
-
when :utf8
|
44
|
-
FFI::Function.new(:int,
|
45
|
-
[:pointer, :pointer],
|
46
|
-
find_support_function('g_str_equal'))
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# @api private
|
51
|
-
def self.find_support_function(name)
|
52
|
-
lib = ::GLib::Lib.ffi_libraries.first
|
53
|
-
lib.find_function(name)
|
54
|
-
end
|
55
|
-
|
56
30
|
def each
|
57
31
|
prc = proc do|keyptr, valptr, _userdata|
|
58
32
|
key = GirFFI::ArgHelper.cast_from_pointer key_type, keyptr
|
@@ -79,5 +53,31 @@ module GLib
|
|
79
53
|
@key_type, @value_type = *typespec
|
80
54
|
self
|
81
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def hash_function_for_key_type
|
60
|
+
case @key_type
|
61
|
+
when :utf8
|
62
|
+
FFI::Function.new(:uint,
|
63
|
+
[:pointer],
|
64
|
+
find_support_function('g_str_hash'))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def equality_function_for_key_type
|
69
|
+
case @key_type
|
70
|
+
when :utf8
|
71
|
+
FFI::Function.new(:int,
|
72
|
+
[:pointer, :pointer],
|
73
|
+
find_support_function('g_str_equal'))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_support_function(name)
|
78
|
+
lib = ::GLib::Lib.ffi_libraries.first
|
79
|
+
lib.find_function(name)
|
80
|
+
end
|
81
|
+
|
82
82
|
end
|
83
83
|
end
|
@@ -11,9 +11,6 @@ module GLib
|
|
11
11
|
replace_method base, :next, :tail
|
12
12
|
replace_method base, :data, :head
|
13
13
|
|
14
|
-
class << base; self end.send :remove_method, :new
|
15
|
-
base.extend ListClassMethods
|
16
|
-
|
17
14
|
base.extend ContainerClassMethods
|
18
15
|
end
|
19
16
|
|
@@ -24,6 +21,11 @@ module GLib
|
|
24
21
|
end
|
25
22
|
end
|
26
23
|
|
24
|
+
def initialize(type)
|
25
|
+
store_pointer(FFI::Pointer.new(0))
|
26
|
+
@element_type = type
|
27
|
+
end
|
28
|
+
|
27
29
|
def each
|
28
30
|
reset_iterator
|
29
31
|
while (elem = next_element)
|
@@ -64,17 +66,5 @@ module GLib
|
|
64
66
|
def element_ptr_for(data)
|
65
67
|
GirFFI::InPointer.from(element_type, data)
|
66
68
|
end
|
67
|
-
|
68
|
-
# Common class methods for List and SList
|
69
|
-
module ListClassMethods
|
70
|
-
# TODO: Make this behave more like a real .new method
|
71
|
-
def new(type)
|
72
|
-
allocate.tap do |it|
|
73
|
-
struct = self::Struct.new(FFI::Pointer.new(0))
|
74
|
-
it.instance_variable_set :@struct, struct
|
75
|
-
it.instance_variable_set :@element_type, type
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
69
|
end
|
80
70
|
end
|
data/lib/ffi-glib/ptr_array.rb
CHANGED
@@ -16,13 +16,13 @@ module GLib
|
|
16
16
|
POINTER_SIZE = FFI.type_size(:pointer)
|
17
17
|
|
18
18
|
class << self
|
19
|
-
remove_method :new
|
20
19
|
# Remove stub generated by builder.
|
21
20
|
remove_method :add if method_defined? :add
|
22
21
|
end
|
23
22
|
|
24
|
-
def
|
25
|
-
|
23
|
+
def initialize(type)
|
24
|
+
@element_type = type
|
25
|
+
store_pointer Lib.g_ptr_array_new
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.from_enumerable(type, it)
|
data/lib/ffi-gobject/closure.rb
CHANGED
@@ -15,14 +15,12 @@ module GObject
|
|
15
15
|
:block_id, :int64
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def initialize(&block)
|
19
19
|
raise ArgumentError unless block_given?
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
closure
|
21
|
+
initialize_simple(self.class::Struct.size, nil)
|
22
|
+
self.block = block
|
23
|
+
set_marshal proc { |*args| self.class.marshaller(*args) }
|
26
24
|
end
|
27
25
|
|
28
26
|
# @api private
|
@@ -36,24 +34,24 @@ module GObject
|
|
36
34
|
|
37
35
|
result = rclosure.invoke_block(*args)
|
38
36
|
|
39
|
-
return_value.
|
40
|
-
end
|
41
|
-
|
42
|
-
# @api private
|
43
|
-
# TODO: Re-structure so block= and invoke_block can become private methods
|
44
|
-
def block=(block)
|
45
|
-
id = block.object_id
|
46
|
-
BLOCK_STORE[id] = block
|
47
|
-
@struct[:block_id] = id
|
37
|
+
return_value.set_value(result) if return_value
|
48
38
|
end
|
49
39
|
|
50
40
|
# @api private
|
41
|
+
# TODO: Re-structure so invoke_block can become a private method
|
51
42
|
def invoke_block(*args)
|
52
43
|
block.call(*args)
|
53
44
|
end
|
54
45
|
|
55
46
|
private
|
56
47
|
|
48
|
+
# @api private
|
49
|
+
def block=(block)
|
50
|
+
id = block.object_id
|
51
|
+
BLOCK_STORE[id] = block
|
52
|
+
@struct[:block_id] = id
|
53
|
+
end
|
54
|
+
|
57
55
|
def block
|
58
56
|
BLOCK_STORE[@struct[:block_id]]
|
59
57
|
end
|
data/lib/ffi-gobject/value.rb
CHANGED
@@ -6,6 +6,7 @@ module GObject
|
|
6
6
|
setup_instance_method 'init'
|
7
7
|
|
8
8
|
def init_with_finalizer(type)
|
9
|
+
return self if [TYPE_NONE, TYPE_INVALID].include? type
|
9
10
|
init_without_finalizer(type).tap do
|
10
11
|
ObjectSpace.define_finalizer self, self.class.make_finalizer(to_ptr)
|
11
12
|
end
|
@@ -20,13 +21,8 @@ module GObject
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
# TODO: Give more generic name
|
24
|
-
def set_ruby_value(val)
|
25
|
-
init_for_ruby_value val if current_gtype == 0
|
26
|
-
set_value val
|
27
|
-
end
|
28
|
-
|
29
24
|
METHOD_MAP = {
|
25
|
+
TYPE_INVALID => [:get_none, :set_none],
|
30
26
|
TYPE_BOOLEAN => [:get_boolean, :set_boolean],
|
31
27
|
TYPE_BOXED => [:get_boxed, :set_boxed],
|
32
28
|
TYPE_CHAR => [:get_char, :set_char],
|
@@ -55,23 +51,6 @@ module GObject
|
|
55
51
|
|
56
52
|
alias_method :value=, :set_value
|
57
53
|
|
58
|
-
CLASS_TO_GTYPE_MAP = {
|
59
|
-
TrueClass => TYPE_BOOLEAN,
|
60
|
-
FalseClass => TYPE_BOOLEAN,
|
61
|
-
Integer => TYPE_INT,
|
62
|
-
String => TYPE_STRING
|
63
|
-
}
|
64
|
-
|
65
|
-
def init_for_ruby_value(val)
|
66
|
-
CLASS_TO_GTYPE_MAP.each do |klass, type|
|
67
|
-
if val.is_a? klass
|
68
|
-
init type
|
69
|
-
return self
|
70
|
-
end
|
71
|
-
end
|
72
|
-
raise "Can't handle #{val.class}"
|
73
|
-
end
|
74
|
-
|
75
54
|
def current_gtype
|
76
55
|
@struct[:g_type]
|
77
56
|
end
|
@@ -99,22 +78,19 @@ module GObject
|
|
99
78
|
|
100
79
|
# TODO: Give more generic name
|
101
80
|
def self.wrap_ruby_value(val)
|
102
|
-
new.tap { |gv| gv.set_ruby_value val }
|
81
|
+
new.tap { |gv| gv.__send__ :set_ruby_value, val }
|
103
82
|
end
|
104
83
|
|
105
84
|
def self.from(val)
|
106
85
|
case val
|
107
86
|
when self
|
108
87
|
val
|
109
|
-
when nil
|
110
|
-
nil
|
111
88
|
else
|
112
89
|
wrap_ruby_value val
|
113
90
|
end
|
114
91
|
end
|
115
92
|
|
116
93
|
def self.for_gtype(gtype)
|
117
|
-
return nil if gtype == TYPE_NONE
|
118
94
|
new.tap do |it|
|
119
95
|
it.init gtype
|
120
96
|
end
|
@@ -130,6 +106,36 @@ module GObject
|
|
130
106
|
|
131
107
|
private
|
132
108
|
|
109
|
+
def set_ruby_value(val)
|
110
|
+
init_for_ruby_value val if uninitialized?
|
111
|
+
set_value val
|
112
|
+
end
|
113
|
+
|
114
|
+
CLASS_TO_GTYPE_MAP = {
|
115
|
+
NilClass => TYPE_INVALID,
|
116
|
+
TrueClass => TYPE_BOOLEAN,
|
117
|
+
FalseClass => TYPE_BOOLEAN,
|
118
|
+
Integer => TYPE_INT,
|
119
|
+
String => TYPE_STRING
|
120
|
+
}
|
121
|
+
|
122
|
+
def init_for_ruby_value(val)
|
123
|
+
CLASS_TO_GTYPE_MAP.each do |klass, type|
|
124
|
+
return init type if val.is_a? klass
|
125
|
+
end
|
126
|
+
raise "Can't handle #{val.class}"
|
127
|
+
end
|
128
|
+
|
129
|
+
def set_none(_)
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_none
|
133
|
+
end
|
134
|
+
|
135
|
+
def uninitialized?
|
136
|
+
current_gtype == TYPE_INVALID
|
137
|
+
end
|
138
|
+
|
133
139
|
def set_instance_enhanced(val)
|
134
140
|
check_type_compatibility val if val
|
135
141
|
set_instance val
|
data/lib/ffi-gobject.rb
CHANGED
@@ -47,9 +47,11 @@ module GObject
|
|
47
47
|
argument_gvalues = sig_info.arguments_to_gvalues object, args
|
48
48
|
return_gvalue = sig_info.gvalue_for_return_value
|
49
49
|
|
50
|
-
signal_emitv argument_gvalues, signal_id, detail_quark, return_gvalue
|
51
|
-
|
52
|
-
return_gvalue
|
50
|
+
result = signal_emitv argument_gvalues, signal_id, detail_quark, return_gvalue
|
51
|
+
# NOTE: Depending on the version of GObjectIntrospection, the result will
|
52
|
+
# be stored in result or return_gvalue. This was changed between versions
|
53
|
+
# 1.44 and 1.46.
|
54
|
+
result || return_gvalue
|
53
55
|
end
|
54
56
|
|
55
57
|
def self.signal_connect(object, detailed_signal, data = nil, after = false, &block)
|
@@ -68,7 +68,7 @@ module GObjectIntrospection
|
|
68
68
|
build_array_method :get_methods
|
69
69
|
|
70
70
|
def find_method(name)
|
71
|
-
IFunctionInfo.wrap(Lib.g_object_info_find_method @gobj, name)
|
71
|
+
IFunctionInfo.wrap(Lib.g_object_info_find_method @gobj, name.to_s)
|
72
72
|
end
|
73
73
|
|
74
74
|
def n_signals
|
@@ -92,7 +92,7 @@ module GObjectIntrospection
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def find_vfunc(name)
|
95
|
-
IVFuncInfo.wrap(Lib.g_object_info_find_vfunc @gobj, name)
|
95
|
+
IVFuncInfo.wrap(Lib.g_object_info_find_vfunc @gobj, name.to_s)
|
96
96
|
end
|
97
97
|
##
|
98
98
|
build_array_method :vfuncs
|
@@ -24,7 +24,7 @@ module GObjectIntrospection
|
|
24
24
|
|
25
25
|
##
|
26
26
|
build_array_method :get_methods
|
27
|
-
# There is a function
|
27
|
+
# There is a function g_struct_info_find_method but it causes a core dump.
|
28
28
|
build_finder_method :find_method, :get_n_methods, :get_method
|
29
29
|
|
30
30
|
def size
|
data/lib/gir_ffi/boxed_base.rb
CHANGED
@@ -23,14 +23,16 @@ module GirFFI
|
|
23
23
|
|
24
24
|
def self.copy_value_to_pointer(value, pointer, offset = 0)
|
25
25
|
size = self::Struct.size
|
26
|
-
|
26
|
+
bytes = if value
|
27
|
+
value.to_ptr.read_bytes(size)
|
28
|
+
else
|
29
|
+
"\x00" * size
|
30
|
+
end
|
31
|
+
pointer.put_bytes offset, bytes, 0, size
|
27
32
|
end
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
obj = allocate
|
32
|
-
obj.instance_variable_set :@struct, self::Struct.new
|
33
|
-
obj
|
34
|
+
def initialize
|
35
|
+
@struct = self.class::Struct.new
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
@@ -14,16 +14,6 @@ module GirFFI
|
|
14
14
|
setup_constants
|
15
15
|
stub_methods
|
16
16
|
setup_field_accessors
|
17
|
-
provide_constructor
|
18
|
-
end
|
19
|
-
|
20
|
-
def provide_constructor
|
21
|
-
return if info.find_method 'new'
|
22
|
-
|
23
|
-
# TODO: Provide both new and initialize
|
24
|
-
(class << klass; self; end).class_eval do
|
25
|
-
alias_method :new, :_allocate
|
26
|
-
end
|
27
17
|
end
|
28
18
|
end
|
29
19
|
end
|
@@ -200,9 +200,9 @@ module GirFFI
|
|
200
200
|
|
201
201
|
def setup_constructor
|
202
202
|
code = <<-CODE
|
203
|
-
def
|
204
|
-
|
205
|
-
|
203
|
+
def initialize
|
204
|
+
ptr = GObject::Lib.g_object_newv #{@gtype}, 0, nil
|
205
|
+
store_pointer(ptr)
|
206
206
|
end
|
207
207
|
CODE
|
208
208
|
klass.class_eval code
|
data/lib/gir_ffi/class_base.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require 'gir_ffi/registered_type_base'
|
3
|
+
require 'gir_ffi/builders/null_class_builder'
|
3
4
|
|
4
5
|
module GirFFI
|
5
6
|
# Base class for all generated classes and structs. Contains code for dealing
|
@@ -8,6 +9,8 @@ module GirFFI
|
|
8
9
|
extend RegisteredTypeBase
|
9
10
|
extend Forwardable
|
10
11
|
|
12
|
+
GIR_FFI_BUILDER = Builders::NullClassBuilder.new
|
13
|
+
|
11
14
|
attr_reader :struct
|
12
15
|
def_delegators :@struct, :to_ptr
|
13
16
|
|
@@ -15,7 +18,7 @@ module GirFFI
|
|
15
18
|
method_name = self.class.try_in_ancestors(:setup_instance_method, method.to_s)
|
16
19
|
|
17
20
|
unless method_name
|
18
|
-
raise "
|
21
|
+
raise NoMethodError, "undefined method `#{method}' for #{self}"
|
19
22
|
end
|
20
23
|
|
21
24
|
send method_name, *arguments, &block
|
@@ -27,11 +30,15 @@ module GirFFI
|
|
27
30
|
other.class == self.class && to_ptr.address == other.to_ptr.address
|
28
31
|
end
|
29
32
|
|
33
|
+
def initialize
|
34
|
+
raise NoMethodError
|
35
|
+
end
|
36
|
+
|
30
37
|
def self.setup_and_call(method, arguments, &block)
|
31
38
|
method_name = try_in_ancestors(:setup_method, method.to_s)
|
32
39
|
|
33
40
|
unless method_name
|
34
|
-
raise "
|
41
|
+
raise NoMethodError, "undefined method `#{method}' for #{self}"
|
35
42
|
end
|
36
43
|
|
37
44
|
send method_name, *arguments, &block
|
@@ -44,6 +51,7 @@ module GirFFI
|
|
44
51
|
return result if result
|
45
52
|
end
|
46
53
|
end
|
54
|
+
nil
|
47
55
|
end
|
48
56
|
|
49
57
|
def self.to_ffi_type
|
@@ -58,10 +66,6 @@ module GirFFI
|
|
58
66
|
gir_ffi_builder.setup_instance_method name
|
59
67
|
end
|
60
68
|
|
61
|
-
class << self
|
62
|
-
undef new
|
63
|
-
end
|
64
|
-
|
65
69
|
# Wrap the passed pointer in an instance of the current class, or a
|
66
70
|
# descendant type if applicable.
|
67
71
|
def self.wrap(ptr)
|
@@ -52,7 +52,7 @@ module GirFFI
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def clear
|
55
|
-
|
55
|
+
put_bytes 0, "\x00" * value_type_size, 0, value_type_size
|
56
56
|
end
|
57
57
|
|
58
58
|
def self.for(type)
|
@@ -72,9 +72,5 @@ module GirFFI
|
|
72
72
|
def value_type_size
|
73
73
|
@value_type_size ||= FFI.type_size value_ffi_type
|
74
74
|
end
|
75
|
-
|
76
|
-
def nil_value
|
77
|
-
value_ffi_type == :pointer ? nil : 0
|
78
|
-
end
|
79
75
|
end
|
80
76
|
end
|
data/lib/gir_ffi/version.rb
CHANGED
@@ -38,7 +38,7 @@ describe GObject::RubyClosure do
|
|
38
38
|
|
39
39
|
it "stores the closure's return value in the proper gvalue" do
|
40
40
|
c = GObject::RubyClosure.new { 2 }
|
41
|
-
gv = GObject::Value.new
|
41
|
+
gv = GObject::Value.new.init GObject::TYPE_INT
|
42
42
|
GObject::RubyClosure.marshaller(c, gv, nil, nil, nil)
|
43
43
|
assert_equal 2, gv.get_value
|
44
44
|
end
|
@@ -18,6 +18,23 @@ describe GObject::Value do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
describe '.for_gtype' do
|
22
|
+
it 'handles char' do
|
23
|
+
gv = GObject::Value.for_gtype GObject::TYPE_CHAR
|
24
|
+
gv.current_gtype.must_equal GObject::TYPE_CHAR
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'handles invalid type' do
|
28
|
+
gv = GObject::Value.for_gtype GObject::TYPE_INVALID
|
29
|
+
gv.current_gtype.must_equal GObject::TYPE_INVALID
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'handles void type' do
|
33
|
+
gv = GObject::Value.for_gtype GObject::TYPE_NONE
|
34
|
+
gv.current_gtype.must_equal GObject::TYPE_INVALID
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
21
38
|
describe '::wrap_ruby_value' do
|
22
39
|
it 'wraps a boolean false' do
|
23
40
|
gv = GObject::Value.wrap_ruby_value false
|
@@ -40,6 +57,12 @@ describe GObject::Value do
|
|
40
57
|
gv = GObject::Value.wrap_ruby_value 'Some Random String'
|
41
58
|
assert_equal 'Some Random String', gv.get_string
|
42
59
|
end
|
60
|
+
|
61
|
+
it 'wraps nil' do
|
62
|
+
gv = GObject::Value.wrap_ruby_value nil
|
63
|
+
assert_instance_of GObject::Value, gv
|
64
|
+
assert_equal nil, gv.get_value
|
65
|
+
end
|
43
66
|
end
|
44
67
|
|
45
68
|
describe '#set_value' do
|
@@ -247,6 +270,12 @@ describe GObject::Value do
|
|
247
270
|
gv2.current_gtype_name.must_equal 'gint'
|
248
271
|
gv2.get_value.must_equal 21
|
249
272
|
end
|
273
|
+
|
274
|
+
it 'creates a null GValue from a Ruby nil' do
|
275
|
+
gv = GObject::Value.from nil
|
276
|
+
gv.current_gtype.must_equal GObject::TYPE_INVALID
|
277
|
+
gv.get_value.must_equal nil
|
278
|
+
end
|
250
279
|
end
|
251
280
|
|
252
281
|
describe '#set_value' do
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'introspection_test_helper'
|
2
|
+
|
3
|
+
describe GObjectIntrospection::IInterfaceInfo do
|
4
|
+
let(:object_info) { get_introspection_data('GObject', 'TypePlugin') }
|
5
|
+
|
6
|
+
describe '#find_method' do
|
7
|
+
it 'finds a method by name string' do
|
8
|
+
object_info.find_method('complete_interface_info').wont_be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'finds a method by name symbol' do
|
12
|
+
object_info.find_method(:complete_interface_info).wont_be_nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#type_name' do
|
17
|
+
it 'returns the correct name' do
|
18
|
+
object_info.type_name.must_equal 'GTypePlugin'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -4,9 +4,23 @@ describe GObjectIntrospection::IObjectInfo do
|
|
4
4
|
let(:object_info) { get_introspection_data('GObject', 'Object') }
|
5
5
|
|
6
6
|
describe '#find_vfunc' do
|
7
|
-
it 'finds a vfunc by name' do
|
7
|
+
it 'finds a vfunc by name string' do
|
8
8
|
object_info.find_vfunc('finalize').wont_be_nil
|
9
9
|
end
|
10
|
+
|
11
|
+
it 'finds a vfunc by name symbol' do
|
12
|
+
object_info.find_vfunc(:finalize).wont_be_nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#find_method' do
|
17
|
+
it 'finds a method by name string' do
|
18
|
+
object_info.find_method('bind_property').wont_be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'finds a method by name symbol' do
|
22
|
+
object_info.find_method(:bind_property).wont_be_nil
|
23
|
+
end
|
10
24
|
end
|
11
25
|
|
12
26
|
describe '#type_name' do
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'introspection_test_helper'
|
2
|
+
|
3
|
+
describe GObjectIntrospection::IStructInfo do
|
4
|
+
let(:object_info) { get_introspection_data('GObject', 'Closure') }
|
5
|
+
|
6
|
+
describe '#find_method' do
|
7
|
+
it 'finds a method by name string' do
|
8
|
+
object_info.find_method('new_simple').wont_be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'finds a method by name symbol' do
|
12
|
+
object_info.find_method(:new_simple).wont_be_nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#type_name' do
|
17
|
+
it 'returns the correct name' do
|
18
|
+
object_info.type_name.must_equal 'GClosure'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'introspection_test_helper'
|
2
|
+
|
3
|
+
describe GObjectIntrospection::IUnionInfo do
|
4
|
+
let(:object_info) { get_introspection_data('GLib', 'Mutex') }
|
5
|
+
|
6
|
+
describe '#find_method' do
|
7
|
+
it 'finds a method by name string' do
|
8
|
+
object_info.find_method('clear').wont_be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'finds a method by name symbol' do
|
12
|
+
object_info.find_method(:clear).wont_be_nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -92,8 +92,7 @@ describe GirFFI::ClassBase do
|
|
92
92
|
'correct-result'
|
93
93
|
end
|
94
94
|
|
95
|
-
def
|
96
|
-
allocate
|
95
|
+
def initialize
|
97
96
|
end
|
98
97
|
end
|
99
98
|
klass.const_set :GIR_FFI_BUILDER, builder
|
@@ -101,6 +100,19 @@ describe GirFFI::ClassBase do
|
|
101
100
|
result = klass.setup_and_call :foo, []
|
102
101
|
result.must_equal 'correct-result'
|
103
102
|
end
|
103
|
+
|
104
|
+
it 'raises a sensible error if the method is not found' do
|
105
|
+
expect(builder = Object.new).to receive(:setup_method).with('foo').and_return nil
|
106
|
+
klass = Class.new GirFFI::ClassBase do
|
107
|
+
def initialize
|
108
|
+
end
|
109
|
+
end
|
110
|
+
klass.const_set :GIR_FFI_BUILDER, builder
|
111
|
+
|
112
|
+
proc { klass.setup_and_call :foo, [] }.
|
113
|
+
must_raise(NoMethodError).message.
|
114
|
+
must_match(/^undefined method `foo' for/)
|
115
|
+
end
|
104
116
|
end
|
105
117
|
|
106
118
|
describe '#setup_and_call' do
|
@@ -114,8 +126,7 @@ describe GirFFI::ClassBase do
|
|
114
126
|
def foo
|
115
127
|
end
|
116
128
|
|
117
|
-
def
|
118
|
-
allocate
|
129
|
+
def initialize
|
119
130
|
end
|
120
131
|
end
|
121
132
|
sub_klass.const_set :GIR_FFI_BUILDER, sub_builder
|
@@ -132,8 +143,7 @@ describe GirFFI::ClassBase do
|
|
132
143
|
'correct-result'
|
133
144
|
end
|
134
145
|
|
135
|
-
def
|
136
|
-
allocate
|
146
|
+
def initialize
|
137
147
|
end
|
138
148
|
end
|
139
149
|
klass.const_set :GIR_FFI_BUILDER, builder
|
@@ -143,5 +153,20 @@ describe GirFFI::ClassBase do
|
|
143
153
|
result = obj.setup_and_call :foo, []
|
144
154
|
result.must_equal 'correct-result'
|
145
155
|
end
|
156
|
+
|
157
|
+
it 'raises a sensible error if the method is not found' do
|
158
|
+
expect(builder = Object.new).to receive(:setup_instance_method).with('foo').and_return nil
|
159
|
+
klass = Class.new GirFFI::ClassBase do
|
160
|
+
def initialize
|
161
|
+
end
|
162
|
+
end
|
163
|
+
klass.const_set :GIR_FFI_BUILDER, builder
|
164
|
+
|
165
|
+
obj = klass.new
|
166
|
+
|
167
|
+
proc { obj.setup_and_call :foo, [] }.
|
168
|
+
must_raise(NoMethodError).message.
|
169
|
+
must_match(/^undefined method `foo' for/)
|
170
|
+
end
|
146
171
|
end
|
147
172
|
end
|
@@ -57,11 +57,30 @@ describe GirFFI::InOutPointer do
|
|
57
57
|
|
58
58
|
describe '.for' do
|
59
59
|
it 'handles :gboolean' do
|
60
|
-
GirFFI::InOutPointer.for :gboolean
|
60
|
+
result = GirFFI::InOutPointer.for :gboolean
|
61
|
+
result.to_value.must_equal false
|
61
62
|
end
|
62
63
|
|
63
64
|
it 'handles :utf8' do
|
64
|
-
GirFFI::InOutPointer.for :utf8
|
65
|
+
result = GirFFI::InOutPointer.for :utf8
|
66
|
+
result.to_value.must_be :null?
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'handles GObject::Value' do
|
70
|
+
result = GirFFI::InOutPointer.for GObject::Value
|
71
|
+
type_size = FFI.type_size GObject::Value
|
72
|
+
expected = "\x00" * type_size
|
73
|
+
result.to_value.read_bytes(type_size).must_equal expected
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#set_value' do
|
78
|
+
it 'works setting the value to nil for GObject::Value' do
|
79
|
+
pointer = GirFFI::InOutPointer.from GObject::Value, GObject::Value.from(3)
|
80
|
+
pointer.set_value nil
|
81
|
+
type_size = FFI.type_size GObject::Value
|
82
|
+
expected = "\x00" * type_size
|
83
|
+
pointer.to_value.read_bytes(type_size).must_equal expected
|
65
84
|
end
|
66
85
|
end
|
67
86
|
|
@@ -76,4 +76,13 @@ describe GirFFI::UserDefinedTypeInfo do
|
|
76
76
|
info.g_name.must_equal 'bar'
|
77
77
|
end
|
78
78
|
end
|
79
|
+
|
80
|
+
describe '#find_method' do
|
81
|
+
let(:klass) { Object.new }
|
82
|
+
let(:info) { GirFFI::UserDefinedTypeInfo.new klass }
|
83
|
+
|
84
|
+
it 'finds no methods' do
|
85
|
+
info.find_method('foo').must_equal nil
|
86
|
+
end
|
87
|
+
end
|
79
88
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gir_ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matijs van Zuijlen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -189,6 +189,7 @@ files:
|
|
189
189
|
- lib/gir_ffi/builders/method_template.rb
|
190
190
|
- lib/gir_ffi/builders/module_builder.rb
|
191
191
|
- lib/gir_ffi/builders/null_argument_builder.rb
|
192
|
+
- lib/gir_ffi/builders/null_class_builder.rb
|
192
193
|
- lib/gir_ffi/builders/null_convertor.rb
|
193
194
|
- lib/gir_ffi/builders/null_return_value_builder.rb
|
194
195
|
- lib/gir_ffi/builders/object_builder.rb
|
@@ -278,10 +279,13 @@ files:
|
|
278
279
|
- test/ffi-gobject_introspection/i_constant_info_test.rb
|
279
280
|
- test/ffi-gobject_introspection/i_enum_info_test.rb
|
280
281
|
- test/ffi-gobject_introspection/i_function_info_test.rb
|
282
|
+
- test/ffi-gobject_introspection/i_interface_info_test.rb
|
281
283
|
- test/ffi-gobject_introspection/i_object_info_test.rb
|
282
284
|
- test/ffi-gobject_introspection/i_registered_type_info_test.rb
|
283
285
|
- test/ffi-gobject_introspection/i_repository_test.rb
|
286
|
+
- test/ffi-gobject_introspection/i_struct_info_test.rb
|
284
287
|
- test/ffi-gobject_introspection/i_type_info_test.rb
|
288
|
+
- test/ffi-gobject_introspection/i_union_info_test.rb
|
285
289
|
- test/ffi-gobject_introspection/lib_test.rb
|
286
290
|
- test/ffi-gobject_test.rb
|
287
291
|
- test/gir_ffi-base/glib/boolean_test.rb
|