gir_ffi 0.0.4 → 0.0.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.
- data/History.txt +9 -0
- data/Rakefile +0 -18
- data/TODO.rdoc +1 -1
- data/lib/gir_ffi/arg_helper.rb +165 -35
- data/lib/gir_ffi/builder.rb +4 -3
- data/lib/gir_ffi/class_base.rb +11 -3
- data/lib/gir_ffi/class_builder.rb +49 -35
- data/lib/gir_ffi/function_definition_builder.rb +194 -64
- data/lib/gir_ffi/i_arg_info.rb +3 -0
- data/lib/gir_ffi/i_callback_info.rb +1 -1
- data/lib/gir_ffi/i_interface_info.rb +67 -2
- data/lib/gir_ffi/i_repository.rb +5 -0
- data/lib/gir_ffi/lib.rb +22 -1
- data/lib/gir_ffi/module_builder.rb +1 -0
- data/lib/gir_ffi/overrides/gobject.rb +16 -13
- data/lib/gir_ffi/overrides/gtk.rb +1 -1
- data/tasks/notes.rake +12 -25
- data/tasks/setup.rb +0 -132
- data/tasks/test.rake +4 -12
- data/test/arg_helper_test.rb +25 -7
- data/test/builder_test.rb +36 -21
- data/test/class_base_test.rb +0 -7
- data/test/class_builder_test.rb +6 -0
- data/test/everything_test.rb +427 -1
- data/test/function_definition_builder_test.rb +69 -12
- data/test/gobject_overrides_test.rb +12 -3
- data/test/test_helper.rb +5 -0
- metadata +8 -10
- data/tasks/bones.rake +0 -87
- data/tasks/post_load.rake +0 -25
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 0.0.5 / 2010-12-30
|
2
|
+
|
3
|
+
* Don't create instance methods out of functions and vice versa.
|
4
|
+
* Find signals on interfaces, too.
|
5
|
+
* Implement tests for most of Everything.
|
6
|
+
* Correctly handle array + size arguments.
|
7
|
+
* Handle most other argument types.
|
8
|
+
* Various internal changes and other fixes.
|
9
|
+
|
1
10
|
== 0.0.4 / 2010-12-14
|
2
11
|
|
3
12
|
* Lots of changes to the internals.
|
data/Rakefile
CHANGED
@@ -1,21 +1,3 @@
|
|
1
|
-
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
-
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
-
# are where the options are used.
|
4
|
-
|
5
1
|
load 'tasks/setup.rb'
|
6
2
|
|
7
|
-
ensure_in_path 'lib'
|
8
|
-
require 'gir_ffi'
|
9
|
-
|
10
3
|
task :default => 'test:run'
|
11
|
-
|
12
|
-
PROJ.name = 'gir_ffi'
|
13
|
-
PROJ.authors = 'Matijs van Zuijlen'
|
14
|
-
PROJ.email = 'matijs@matijs.net'
|
15
|
-
PROJ.url = 'http://www.github.com/mvz/ruby-gir-ffi'
|
16
|
-
PROJ.version = GirFFI::VERSION
|
17
|
-
PROJ.readme_file = 'README.rdoc'
|
18
|
-
|
19
|
-
PROJ.exclude << ["^tmp/", "\\.swp$", "^\\.gitignore$", "^\\.autotest$"]
|
20
|
-
|
21
|
-
# EOF
|
data/TODO.rdoc
CHANGED
@@ -21,7 +21,7 @@ distinguished, based on the GIR data, from methods that take a pointer to
|
|
21
21
|
any GObject.
|
22
22
|
|
23
23
|
I'm currently passing the object id as the value of the 'gpointer'. Special
|
24
|
-
|
24
|
+
overrides will have to be used for the cases where the 'gpointer' actually
|
25
25
|
needs to be a GObject. I consider it an omission in GIRepository that these
|
26
26
|
two cases are not distinguished.
|
27
27
|
|
data/lib/gir_ffi/arg_helper.rb
CHANGED
@@ -8,68 +8,179 @@ module GirFFI
|
|
8
8
|
FFI::Pointer.new(obj.object_id)
|
9
9
|
end
|
10
10
|
|
11
|
+
def self.typed_array_to_inptr type, ary
|
12
|
+
return nil if ary.nil?
|
13
|
+
block = allocate_array_of_type type, ary.length
|
14
|
+
block.send "put_array_of_#{type}", 0, ary
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.int32_array_to_inptr ary
|
18
|
+
typed_array_to_inptr :int32, ary
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO: Use alias.
|
22
|
+
def self.int_array_to_inptr ary
|
23
|
+
int32_array_to_inptr ary
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.int16_array_to_inptr ary
|
27
|
+
typed_array_to_inptr :int16, ary
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.int64_array_to_inptr ary
|
31
|
+
typed_array_to_inptr :int64, ary
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.int8_array_to_inptr ary
|
35
|
+
typed_array_to_inptr :int8, ary
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.utf8_to_inptr str
|
39
|
+
return nil if str.nil?
|
40
|
+
len = str.bytesize
|
41
|
+
AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.GType_array_to_inptr ary
|
45
|
+
case FFI.type_size(:size_t)
|
46
|
+
when 4
|
47
|
+
int32_array_to_inptr ary
|
48
|
+
when 8
|
49
|
+
int64_array_to_inptr ary
|
50
|
+
else
|
51
|
+
raise RuntimeError, "Unexpected size of :size_t"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.cleanup_ptr ptr
|
56
|
+
LibC.free ptr
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.cleanup_ptr_ptr ptr
|
60
|
+
block = ptr.read_pointer
|
61
|
+
LibC.free ptr
|
62
|
+
LibC.free block
|
63
|
+
end
|
64
|
+
|
65
|
+
# Takes an outptr to a pointer array, and frees all pointers.
|
66
|
+
def self.cleanup_ptr_array_ptr ptr, size
|
67
|
+
return if ptr.nil?
|
68
|
+
|
69
|
+
block = ptr.read_pointer
|
70
|
+
LibC.free ptr
|
71
|
+
|
72
|
+
return if block.null?
|
73
|
+
|
74
|
+
ptrs = block.read_array_of_pointer(size)
|
75
|
+
LibC.free block
|
76
|
+
|
77
|
+
ptrs.map do |p|
|
78
|
+
LibC.free p unless p.null?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
11
82
|
def self.int_to_inoutptr val
|
12
|
-
|
13
|
-
|
14
|
-
|
83
|
+
int_pointer.write_int val
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.utf8_to_inoutptr str
|
87
|
+
sptr = utf8_to_inptr str
|
88
|
+
pointer_pointer.write_pointer sptr
|
15
89
|
end
|
16
90
|
|
17
|
-
def self.
|
91
|
+
def self.int_array_to_inoutptr ary
|
92
|
+
block = int_array_to_inptr ary
|
93
|
+
pointer_pointer.write_pointer block
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.utf8_array_to_inoutptr ary
|
18
97
|
return nil if ary.nil?
|
19
98
|
|
20
|
-
ptrs = ary.map {|str|
|
21
|
-
len = str.bytesize
|
22
|
-
AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0)
|
23
|
-
}
|
99
|
+
ptrs = ary.map {|str| utf8_to_inptr str}
|
24
100
|
|
25
|
-
|
26
|
-
block = AllocationHelper.safe_malloc ptr_size * ptrs.length
|
101
|
+
block = AllocationHelper.safe_malloc FFI.type_size(:pointer) * ptrs.length
|
27
102
|
block.write_array_of_pointer ptrs
|
28
103
|
|
29
|
-
|
30
|
-
argv.write_pointer block
|
31
|
-
argv
|
104
|
+
pointer_pointer.write_pointer block
|
32
105
|
end
|
33
106
|
|
34
107
|
def self.double_to_inoutptr val
|
35
|
-
|
36
|
-
|
37
|
-
|
108
|
+
double_pointer.put_double 0, val
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.int_pointer
|
112
|
+
AllocationHelper.safe_malloc FFI.type_size(:int)
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.double_pointer
|
116
|
+
AllocationHelper.safe_malloc FFI.type_size(:double)
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.pointer_pointer
|
120
|
+
AllocationHelper.safe_malloc FFI.type_size(:pointer)
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.int_outptr
|
124
|
+
int_pointer.write_int 0
|
38
125
|
end
|
39
126
|
|
40
|
-
|
127
|
+
def self.double_outptr
|
128
|
+
double_pointer.write_double 0.0
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.pointer_outptr
|
132
|
+
pointer_pointer.write_pointer nil
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.utf8_outptr
|
136
|
+
pointer_outptr
|
137
|
+
end
|
138
|
+
|
139
|
+
# Converts an outptr to a pointer.
|
140
|
+
def self.outptr_to_pointer ptr
|
141
|
+
ptr.read_pointer
|
142
|
+
end
|
143
|
+
|
144
|
+
# Converts an outptr to an int.
|
41
145
|
def self.outptr_to_int ptr
|
42
|
-
|
43
|
-
LibC.free ptr
|
44
|
-
value
|
146
|
+
ptr.read_int
|
45
147
|
end
|
46
148
|
|
47
|
-
# Converts an outptr to a string
|
48
|
-
def self.
|
149
|
+
# Converts an outptr to a string.
|
150
|
+
def self.outptr_to_utf8 ptr
|
49
151
|
return nil if ptr.nil?
|
152
|
+
sptr = ptr.read_pointer
|
50
153
|
|
51
|
-
|
52
|
-
|
154
|
+
sptr.null? ? nil : sptr.read_string
|
155
|
+
end
|
53
156
|
|
157
|
+
# Converts an outptr to a string array.
|
158
|
+
def self.outptr_to_utf8_array ptr, size
|
159
|
+
return nil if ptr.nil?
|
160
|
+
block = ptr.read_pointer
|
54
161
|
return nil if block.null?
|
55
|
-
|
56
162
|
ptrs = block.read_array_of_pointer(size)
|
57
|
-
LibC.free block
|
58
163
|
|
59
164
|
ptrs.map do |p|
|
60
|
-
|
61
|
-
nil
|
62
|
-
else
|
63
|
-
p.read_string.tap { LibC.free p }
|
64
|
-
end
|
165
|
+
p.null? ? nil : p.read_string
|
65
166
|
end
|
66
167
|
end
|
67
168
|
|
68
|
-
# Converts an outptr to a double
|
169
|
+
# Converts an outptr to a double.
|
69
170
|
def self.outptr_to_double ptr
|
70
|
-
|
71
|
-
|
72
|
-
|
171
|
+
ptr.get_double 0
|
172
|
+
end
|
173
|
+
|
174
|
+
# Converts an outptr to an array of int.
|
175
|
+
def self.outptr_to_int_array ptr, size
|
176
|
+
return nil if ptr.null?
|
177
|
+
block = ptr.read_pointer
|
178
|
+
return nil if block.null?
|
179
|
+
ptr_to_int_array block, size
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.ptr_to_int_array ptr, size
|
183
|
+
ptr.read_array_of_int(size)
|
73
184
|
end
|
74
185
|
|
75
186
|
def self.mapped_callback_args prc=nil, &block
|
@@ -104,5 +215,24 @@ module GirFFI
|
|
104
215
|
GirFFI::GObject.object_ref_sink(gobject)
|
105
216
|
end
|
106
217
|
end
|
218
|
+
|
219
|
+
def self.check_fixed_array_size size, arr, name
|
220
|
+
unless arr.size == size
|
221
|
+
raise ArgumentError, "#{name} should have size #{size}"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.allocate_array_of_type type, length
|
226
|
+
AllocationHelper.safe_malloc FFI.type_size(type) * length
|
227
|
+
end
|
228
|
+
|
229
|
+
# FIXME: Quasi-circular dependency on generated module
|
230
|
+
def self.object_pointer_to_object optr
|
231
|
+
tp = ::GObject.type_from_instance_pointer optr
|
232
|
+
gir = GirFFI::IRepository.default
|
233
|
+
info = gir.find_by_gtype tp
|
234
|
+
klass = GirFFI::Builder.build_class info.namespace, info.name
|
235
|
+
klass.wrap optr
|
236
|
+
end
|
107
237
|
end
|
108
238
|
end
|
data/lib/gir_ffi/builder.rb
CHANGED
@@ -31,7 +31,8 @@ module GirFFI
|
|
31
31
|
|
32
32
|
def self.ffi_function_argument_types info
|
33
33
|
types = info.args.map do |a|
|
34
|
-
iarginfo_to_ffitype a
|
34
|
+
tp = iarginfo_to_ffitype a
|
35
|
+
tp == :string ? :pointer : tp
|
35
36
|
end
|
36
37
|
if info.type == :function
|
37
38
|
types.unshift :pointer if info.method?
|
@@ -65,8 +66,8 @@ module GirFFI
|
|
65
66
|
end
|
66
67
|
when :boolean
|
67
68
|
return :bool
|
68
|
-
when :GType
|
69
|
-
return :
|
69
|
+
when :GType, :size
|
70
|
+
return :size_t
|
70
71
|
else
|
71
72
|
return tag
|
72
73
|
end
|
data/lib/gir_ffi/class_base.rb
CHANGED
@@ -7,7 +7,6 @@ module GirFFI
|
|
7
7
|
def_delegators :@struct, :[], :[]=, :to_ptr
|
8
8
|
|
9
9
|
def initialize(*args)
|
10
|
-
# TODO: Handle NULL pointer.
|
11
10
|
@struct = ffi_structure.new(*args)
|
12
11
|
end
|
13
12
|
|
@@ -19,13 +18,13 @@ module GirFFI
|
|
19
18
|
self.class.gir_ffi_builder
|
20
19
|
end
|
21
20
|
|
22
|
-
def
|
21
|
+
def setup_and_call method, *arguments, &block
|
23
22
|
result = gir_ffi_builder.setup_instance_method method.to_s
|
24
23
|
return super unless result
|
25
24
|
self.send method, *arguments, &block
|
26
25
|
end
|
27
26
|
|
28
|
-
def self.
|
27
|
+
def self.setup_and_call method, *arguments, &block
|
29
28
|
result = gir_ffi_builder.setup_method method.to_s
|
30
29
|
return super unless result
|
31
30
|
self.send method, *arguments, &block
|
@@ -46,6 +45,15 @@ module GirFFI
|
|
46
45
|
|
47
46
|
alias_method :_real_new, :new
|
48
47
|
undef new
|
48
|
+
|
49
|
+
def wrap ptr
|
50
|
+
return nil if ptr.nil? or ptr.null?
|
51
|
+
_real_new ptr
|
52
|
+
end
|
53
|
+
|
54
|
+
def allocate
|
55
|
+
_real_new
|
56
|
+
end
|
49
57
|
end
|
50
58
|
end
|
51
59
|
end
|
@@ -14,21 +14,18 @@ module GirFFI
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def setup_method method
|
17
|
-
definition = prepare_method method.to_s
|
18
|
-
|
19
|
-
return false if definition.nil?
|
20
|
-
|
21
17
|
klass = build_class
|
22
18
|
meta = (class << klass; self; end)
|
23
|
-
meta.class_eval definition
|
24
19
|
|
25
|
-
|
20
|
+
go = method_introspection_data method
|
21
|
+
return attach_and_define_method method, go, meta
|
26
22
|
end
|
27
23
|
|
28
24
|
def setup_instance_method method
|
29
|
-
|
25
|
+
go = instance_method_introspection_data method
|
26
|
+
result = attach_and_define_method method, go, build_class
|
30
27
|
|
31
|
-
|
28
|
+
unless result
|
32
29
|
if parent
|
33
30
|
return superclass.gir_ffi_builder.setup_instance_method method
|
34
31
|
else
|
@@ -36,10 +33,6 @@ module GirFFI
|
|
36
33
|
end
|
37
34
|
end
|
38
35
|
|
39
|
-
klass = build_class
|
40
|
-
klass.class_eval "undef #{method}"
|
41
|
-
klass.class_eval definition
|
42
|
-
|
43
36
|
true
|
44
37
|
end
|
45
38
|
|
@@ -47,6 +40,13 @@ module GirFFI
|
|
47
40
|
info.signals.each do |s|
|
48
41
|
return s if s.name == signal_name
|
49
42
|
end
|
43
|
+
if info.type == :object
|
44
|
+
info.interfaces.each do |i|
|
45
|
+
i.signals.each do |s|
|
46
|
+
return s if s.name == signal_name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
50
|
if info.parent
|
51
51
|
return superclass.gir_ffi_builder.find_signal signal_name
|
52
52
|
end
|
@@ -58,16 +58,11 @@ module GirFFI
|
|
58
58
|
unless defined? @klass
|
59
59
|
case info.type
|
60
60
|
when :object, :struct
|
61
|
-
|
62
|
-
setup_class unless already_set_up
|
61
|
+
instantiate_struct_class
|
63
62
|
when :union
|
64
63
|
instantiate_union_class
|
65
|
-
setup_class unless already_set_up
|
66
64
|
when :enum, :flags
|
67
|
-
|
68
|
-
vals = info.values.map {|v| [v.name.to_sym, v.value]}.flatten
|
69
|
-
lib.enum(@classname.to_sym, vals)
|
70
|
-
end
|
65
|
+
instantiate_enum_class
|
71
66
|
else
|
72
67
|
raise NotImplementedError, "Cannot build classes of type #{info.type}"
|
73
68
|
end
|
@@ -109,20 +104,29 @@ module GirFFI
|
|
109
104
|
@lib ||= namespace_module.const_get :Lib
|
110
105
|
end
|
111
106
|
|
112
|
-
def
|
107
|
+
def instantiate_struct_class
|
113
108
|
@klass = get_or_define_class namespace_module, @classname, superclass
|
114
109
|
@structklass = get_or_define_class @klass, :Struct, FFI::Struct
|
110
|
+
setup_class unless already_set_up
|
115
111
|
end
|
116
112
|
|
117
113
|
def instantiate_union_class
|
118
114
|
@klass = get_or_define_class namespace_module, @classname, superclass
|
119
115
|
@structklass = get_or_define_class @klass, :Struct, FFI::Union
|
116
|
+
setup_class unless already_set_up
|
117
|
+
end
|
118
|
+
|
119
|
+
def instantiate_enum_class
|
120
|
+
@klass = optionally_define_constant namespace_module, @classname do
|
121
|
+
vals = info.values.map {|v| [v.name.to_sym, v.value]}.flatten
|
122
|
+
lib.enum(@classname.to_sym, vals)
|
123
|
+
end
|
120
124
|
end
|
121
125
|
|
122
126
|
def setup_class
|
123
127
|
setup_layout
|
124
128
|
setup_constants
|
125
|
-
|
129
|
+
stub_methods
|
126
130
|
setup_gtype_getter
|
127
131
|
|
128
132
|
setup_vfunc_invokers if info.type == :object
|
@@ -140,6 +144,8 @@ module GirFFI
|
|
140
144
|
if fields.empty?
|
141
145
|
if parent
|
142
146
|
return [:parent, superclass.const_get(:Struct), 0]
|
147
|
+
else
|
148
|
+
return [:dummy, :char, 0]
|
143
149
|
end
|
144
150
|
end
|
145
151
|
|
@@ -161,20 +167,24 @@ module GirFFI
|
|
161
167
|
ffitype
|
162
168
|
end
|
163
169
|
|
164
|
-
def
|
170
|
+
def stub_methods
|
165
171
|
info.methods.each do |m|
|
166
|
-
@klass.class_eval "
|
167
|
-
def #{m.name} *args, &block
|
168
|
-
method_missing :#{m.name}, *args, &block
|
169
|
-
end
|
170
|
-
"
|
172
|
+
@klass.class_eval method_stub(m.method? ? m.name : "self.#{m.name}", m.name)
|
171
173
|
end
|
172
174
|
end
|
173
175
|
|
176
|
+
def method_stub name, symbol
|
177
|
+
"
|
178
|
+
def #{name} *args, &block
|
179
|
+
setup_and_call :#{symbol}, *args, &block
|
180
|
+
end
|
181
|
+
"
|
182
|
+
end
|
183
|
+
|
174
184
|
def setup_gtype_getter
|
175
185
|
getter = info.type_init
|
176
186
|
return if getter.nil? or getter == "intern"
|
177
|
-
lib.attach_function getter.to_sym, [], :
|
187
|
+
lib.attach_function getter.to_sym, [], :size_t
|
178
188
|
@klass.class_eval "
|
179
189
|
def self.get_gtype
|
180
190
|
::#{lib}.#{getter}
|
@@ -200,7 +210,7 @@ module GirFFI
|
|
200
210
|
return if info.find_method 'new'
|
201
211
|
|
202
212
|
(class << @klass; self; end).class_eval {
|
203
|
-
alias_method :new, :
|
213
|
+
alias_method :new, :allocate
|
204
214
|
}
|
205
215
|
end
|
206
216
|
|
@@ -217,17 +227,21 @@ module GirFFI
|
|
217
227
|
info.find_method method
|
218
228
|
end
|
219
229
|
|
230
|
+
def instance_method_introspection_data method
|
231
|
+
m = method_introspection_data method
|
232
|
+
return !m.nil? && m.method? ? m : nil
|
233
|
+
end
|
234
|
+
|
220
235
|
def function_definition go
|
221
236
|
FunctionDefinitionBuilder.new(go, lib).generate
|
222
237
|
end
|
223
238
|
|
224
|
-
def
|
225
|
-
|
226
|
-
|
227
|
-
return nil if go.nil?
|
228
|
-
|
239
|
+
def attach_and_define_method method, go, modul
|
240
|
+
return false if go.nil?
|
229
241
|
Builder.attach_ffi_function lib, go
|
230
|
-
|
242
|
+
modul.class_eval { remove_method method }
|
243
|
+
modul.class_eval function_definition(go)
|
244
|
+
true
|
231
245
|
end
|
232
246
|
|
233
247
|
def gir
|