gir_ffi 0.0.5 → 0.0.6
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 +8 -0
- data/lib/gir_ffi/arg_helper.rb +55 -37
- data/lib/gir_ffi/argument_builder.rb +382 -0
- data/lib/gir_ffi/builder.rb +4 -4
- data/lib/gir_ffi/class_builder.rb +36 -33
- data/lib/gir_ffi/function_definition_builder.rb +50 -277
- data/lib/gir_ffi/g_object.rb +9 -8
- data/lib/gir_ffi/i_repository.rb +2 -2
- data/lib/gir_ffi/lib.rb +4 -2
- data/lib/gir_ffi/overrides/gobject.rb +43 -41
- data/lib/gir_ffi.rb +0 -34
- data/test/arg_helper_test.rb +19 -13
- data/test/builder_test.rb +0 -1
- data/test/class_base_test.rb +0 -1
- data/test/class_builder_test.rb +0 -1
- data/test/function_definition_builder_test.rb +2 -4
- data/test/{gobject_overrides_test.rb → g_object_overrides_test.rb} +0 -1
- data/test/g_object_test.rb +0 -1
- data/test/{everything_test.rb → generated_everything_test.rb} +13 -14
- data/test/generated_gio_test.rb +32 -0
- data/test/generated_gtk_test.rb +65 -0
- data/test/girffi_test.rb +0 -1
- data/test/gtk_overrides_test.rb +1 -1
- data/test/i_object_info_test.rb +0 -1
- data/test/i_repository_test.rb +0 -1
- data/test/module_builder_test.rb +0 -1
- data/test/test_helper.rb +11 -0
- metadata +13 -8
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
== 0.0.6 / 2011-03-01
|
2
|
+
|
3
|
+
* Cast returned GObjects to their actual type.
|
4
|
+
* Properly cast callback arguments.
|
5
|
+
* Handle the case where functions formally return interfaces.
|
6
|
+
* Make sure Gtk::Window has the correct number of references after creation.
|
7
|
+
* Refactoring and some small fixes.
|
8
|
+
|
1
9
|
== 0.0.5 / 2010-12-30
|
2
10
|
|
3
11
|
* Don't create instance methods out of functions and vice versa.
|
data/lib/gir_ffi/arg_helper.rb
CHANGED
@@ -41,7 +41,7 @@ module GirFFI
|
|
41
41
|
AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0)
|
42
42
|
end
|
43
43
|
|
44
|
-
def self.
|
44
|
+
def self.gtype_array_to_inptr ary
|
45
45
|
case FFI.type_size(:size_t)
|
46
46
|
when 4
|
47
47
|
int32_array_to_inptr ary
|
@@ -64,8 +64,6 @@ module GirFFI
|
|
64
64
|
|
65
65
|
# Takes an outptr to a pointer array, and frees all pointers.
|
66
66
|
def self.cleanup_ptr_array_ptr ptr, size
|
67
|
-
return if ptr.nil?
|
68
|
-
|
69
67
|
block = ptr.read_pointer
|
70
68
|
LibC.free ptr
|
71
69
|
|
@@ -74,9 +72,7 @@ module GirFFI
|
|
74
72
|
ptrs = block.read_array_of_pointer(size)
|
75
73
|
LibC.free block
|
76
74
|
|
77
|
-
ptrs.
|
78
|
-
LibC.free p unless p.null?
|
79
|
-
end
|
75
|
+
ptrs.each { |ptr| LibC.free ptr }
|
80
76
|
end
|
81
77
|
|
82
78
|
def self.int_to_inoutptr val
|
@@ -148,22 +144,16 @@ module GirFFI
|
|
148
144
|
|
149
145
|
# Converts an outptr to a string.
|
150
146
|
def self.outptr_to_utf8 ptr
|
151
|
-
|
152
|
-
sptr = ptr.read_pointer
|
153
|
-
|
154
|
-
sptr.null? ? nil : sptr.read_string
|
147
|
+
ptr_to_utf8 ptr.read_pointer
|
155
148
|
end
|
156
149
|
|
157
150
|
# Converts an outptr to a string array.
|
158
151
|
def self.outptr_to_utf8_array ptr, size
|
159
|
-
return nil if ptr.nil?
|
160
152
|
block = ptr.read_pointer
|
161
153
|
return nil if block.null?
|
162
154
|
ptrs = block.read_array_of_pointer(size)
|
163
155
|
|
164
|
-
ptrs.map
|
165
|
-
p.null? ? nil : p.read_string
|
166
|
-
end
|
156
|
+
ptrs.map { |ptr| ptr_to_utf8 ptr }
|
167
157
|
end
|
168
158
|
|
169
159
|
# Converts an outptr to a double.
|
@@ -173,7 +163,6 @@ module GirFFI
|
|
173
163
|
|
174
164
|
# Converts an outptr to an array of int.
|
175
165
|
def self.outptr_to_int_array ptr, size
|
176
|
-
return nil if ptr.null?
|
177
166
|
block = ptr.read_pointer
|
178
167
|
return nil if block.null?
|
179
168
|
ptr_to_int_array block, size
|
@@ -183,25 +172,50 @@ module GirFFI
|
|
183
172
|
ptr.read_array_of_int(size)
|
184
173
|
end
|
185
174
|
|
186
|
-
def self.
|
175
|
+
def self.ptr_to_utf8 ptr
|
176
|
+
ptr.null? ? nil : ptr.read_string
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.wrap_in_callback_args_mapper namespace, name, prc
|
187
180
|
return prc if FFI::Function === prc
|
188
|
-
if prc.nil?
|
189
|
-
|
190
|
-
prc = block
|
191
|
-
end
|
181
|
+
return nil if prc.nil?
|
182
|
+
info = gir.find_by_name namespace, name
|
192
183
|
return Proc.new do |*args|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
184
|
+
prc.call(*map_callback_args(args, info))
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def self.map_callback_args args, info
|
189
|
+
args.zip(info.args).map { |arg, inf|
|
190
|
+
map_single_callback_arg arg, inf }
|
191
|
+
end
|
192
|
+
|
193
|
+
def self.map_single_callback_arg arg, info
|
194
|
+
type = info.type
|
195
|
+
tag = type.tag
|
196
|
+
|
197
|
+
case tag
|
198
|
+
when :interface
|
199
|
+
iface = type.interface
|
200
|
+
if iface.type == :object
|
201
|
+
object_pointer_to_object arg
|
202
|
+
else
|
203
|
+
arg
|
204
|
+
end
|
205
|
+
when :utf8
|
206
|
+
ptr_to_utf8 arg
|
207
|
+
when :void
|
208
|
+
if arg.null?
|
209
|
+
nil
|
210
|
+
else
|
211
|
+
begin
|
212
|
+
ObjectSpace._id2ref arg.address
|
213
|
+
rescue RangeError
|
201
214
|
arg
|
202
215
|
end
|
203
|
-
|
204
|
-
|
216
|
+
end
|
217
|
+
else
|
218
|
+
arg
|
205
219
|
end
|
206
220
|
end
|
207
221
|
|
@@ -210,12 +224,6 @@ module GirFFI
|
|
210
224
|
raise GError.new(errp)[:message] unless errp.null?
|
211
225
|
end
|
212
226
|
|
213
|
-
def self.sink_if_floating gobject
|
214
|
-
if GirFFI::GObject.object_is_floating(gobject)
|
215
|
-
GirFFI::GObject.object_ref_sink(gobject)
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
227
|
def self.check_fixed_array_size size, arr, name
|
220
228
|
unless arr.size == size
|
221
229
|
raise ArgumentError, "#{name} should have size #{size}"
|
@@ -228,11 +236,21 @@ module GirFFI
|
|
228
236
|
|
229
237
|
# FIXME: Quasi-circular dependency on generated module
|
230
238
|
def self.object_pointer_to_object optr
|
239
|
+
return nil if optr.null?
|
231
240
|
tp = ::GObject.type_from_instance_pointer optr
|
232
|
-
gir = GirFFI::IRepository.default
|
233
241
|
info = gir.find_by_gtype tp
|
242
|
+
|
243
|
+
if info.nil?
|
244
|
+
tpname = ::GObject.type_name tp
|
245
|
+
raise RuntimeError, "Unable to find info for type '#{tpname}' (#{tp})"
|
246
|
+
end
|
247
|
+
|
234
248
|
klass = GirFFI::Builder.build_class info.namespace, info.name
|
235
249
|
klass.wrap optr
|
236
250
|
end
|
251
|
+
|
252
|
+
def self.gir
|
253
|
+
gir = GirFFI::IRepository.default
|
254
|
+
end
|
237
255
|
end
|
238
256
|
end
|
@@ -0,0 +1,382 @@
|
|
1
|
+
module GirFFI
|
2
|
+
# Abstract parent class of the argument building classes. These classes
|
3
|
+
# are used by FunctionDefinitionBuilder to create the code that processes
|
4
|
+
# each argument before and after the actual function call.
|
5
|
+
class ArgumentBuilder
|
6
|
+
KEYWORDS = [
|
7
|
+
"alias", "and", "begin", "break", "case", "class", "def", "do",
|
8
|
+
"else", "elsif", "end", "ensure", "false", "for", "if", "in",
|
9
|
+
"module", "next", "nil", "not", "or", "redo", "rescue", "retry",
|
10
|
+
"return", "self", "super", "then", "true", "undef", "unless",
|
11
|
+
"until", "when", "while", "yield"
|
12
|
+
]
|
13
|
+
|
14
|
+
attr_reader :arginfo, :callarg, :pre, :post, :postpost
|
15
|
+
|
16
|
+
attr_accessor :length_arg, :inarg, :retval
|
17
|
+
|
18
|
+
def initialize function_builder, arginfo=nil, libmodule=nil
|
19
|
+
@arginfo = arginfo
|
20
|
+
@inarg = nil
|
21
|
+
@callarg = nil
|
22
|
+
@retval = nil
|
23
|
+
@retname = nil
|
24
|
+
@name = nil
|
25
|
+
@pre = []
|
26
|
+
@post = []
|
27
|
+
@postpost = []
|
28
|
+
@function_builder = function_builder
|
29
|
+
@libmodule = libmodule
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.build function_builder, arginfo, libmodule
|
33
|
+
klass = case arginfo.direction
|
34
|
+
when :inout
|
35
|
+
InOutArgumentBuilder
|
36
|
+
when :in
|
37
|
+
InArgumentBuilder
|
38
|
+
when :out
|
39
|
+
OutArgumentBuilder
|
40
|
+
else
|
41
|
+
raise ArgumentError
|
42
|
+
end
|
43
|
+
klass.new function_builder, arginfo, libmodule
|
44
|
+
end
|
45
|
+
|
46
|
+
def type
|
47
|
+
@arginfo.type
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def safe name
|
53
|
+
if KEYWORDS.include? name
|
54
|
+
"#{name}_"
|
55
|
+
else
|
56
|
+
name
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Implements argument processing for arguments with direction :in
|
62
|
+
class InArgumentBuilder < ArgumentBuilder
|
63
|
+
def prepare
|
64
|
+
@name = safe(@arginfo.name)
|
65
|
+
@callarg = @function_builder.new_var
|
66
|
+
@inarg = @name
|
67
|
+
end
|
68
|
+
|
69
|
+
def process
|
70
|
+
case @arginfo.type.tag
|
71
|
+
when :interface
|
72
|
+
process_interface_in_arg
|
73
|
+
when :void
|
74
|
+
process_void_in_arg
|
75
|
+
when :array
|
76
|
+
process_array_in_arg
|
77
|
+
when :utf8
|
78
|
+
process_utf8_in_arg
|
79
|
+
else
|
80
|
+
process_other_in_arg
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
|
87
|
+
def process_interface_in_arg
|
88
|
+
arg = @arginfo
|
89
|
+
type = arg.type
|
90
|
+
|
91
|
+
iface = type.interface
|
92
|
+
if iface.type == :callback
|
93
|
+
@pre << "#{@callarg} = GirFFI::ArgHelper.wrap_in_callback_args_mapper \"#{iface.namespace}\", \"#{iface.name}\", #{@inarg}"
|
94
|
+
@pre << "::#{@libmodule}::CALLBACKS << #{@callarg}"
|
95
|
+
else
|
96
|
+
@pre << "#{@callarg} = #{@inarg}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def process_void_in_arg
|
101
|
+
@pre << "#{@callarg} = GirFFI::ArgHelper.object_to_inptr #{@inarg}"
|
102
|
+
end
|
103
|
+
|
104
|
+
def process_utf8_in_arg
|
105
|
+
@pre << "#{@callarg} = GirFFI::ArgHelper.utf8_to_inptr #{@name}"
|
106
|
+
# TODO:
|
107
|
+
#@post << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
|
108
|
+
end
|
109
|
+
|
110
|
+
def process_array_in_arg
|
111
|
+
arg = @arginfo
|
112
|
+
type = arg.type
|
113
|
+
|
114
|
+
if type.array_fixed_size > 0
|
115
|
+
@pre << "GirFFI::ArgHelper.check_fixed_array_size #{type.array_fixed_size}, #{@inarg}, \"#{@inarg}\""
|
116
|
+
elsif type.array_length > -1
|
117
|
+
idx = type.array_length
|
118
|
+
lenvar = @length_arg.inarg
|
119
|
+
@length_arg.inarg = nil
|
120
|
+
@length_arg.pre.unshift "#{lenvar} = #{@inarg}.nil? ? 0 : #{@inarg}.length"
|
121
|
+
end
|
122
|
+
|
123
|
+
tag = arg.type.param_type(0).tag.to_s.downcase
|
124
|
+
@pre << "#{@callarg} = GirFFI::ArgHelper.#{tag}_array_to_inptr #{@inarg}"
|
125
|
+
unless arg.ownership_transfer == :everything
|
126
|
+
if tag == :utf8
|
127
|
+
@post << "GirFFI::ArgHelper.cleanup_ptr_ptr #{@callarg}"
|
128
|
+
else
|
129
|
+
@post << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def process_other_in_arg
|
135
|
+
@pre << "#{@callarg} = #{@name}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Implements argument processing for arguments with direction :out
|
140
|
+
class OutArgumentBuilder < ArgumentBuilder
|
141
|
+
def prepare
|
142
|
+
@name = safe(@arginfo.name)
|
143
|
+
@callarg = @function_builder.new_var
|
144
|
+
@retname = @retval = @function_builder.new_var
|
145
|
+
end
|
146
|
+
|
147
|
+
def process
|
148
|
+
case @arginfo.type.tag
|
149
|
+
when :interface
|
150
|
+
process_interface_out_arg
|
151
|
+
when :array
|
152
|
+
process_array_out_arg
|
153
|
+
else
|
154
|
+
process_other_out_arg
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def process_interface_out_arg
|
161
|
+
iface = @arginfo.type.interface
|
162
|
+
klass = "#{iface.namespace}::#{iface.name}"
|
163
|
+
|
164
|
+
if @arginfo.caller_allocates?
|
165
|
+
@pre << "#{@callarg} = #{klass}.allocate"
|
166
|
+
@post << "#{@retval} = #{@callarg}"
|
167
|
+
else
|
168
|
+
@pre << "#{@callarg} = GirFFI::ArgHelper.pointer_outptr"
|
169
|
+
@post << "#{@retval} = #{klass}.wrap GirFFI::ArgHelper.outptr_to_pointer(#{@callarg})"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def process_array_out_arg
|
174
|
+
@pre << "#{@callarg} = GirFFI::ArgHelper.pointer_outptr"
|
175
|
+
|
176
|
+
arg = @arginfo
|
177
|
+
type = arg.type
|
178
|
+
tag = type.param_type(0).tag
|
179
|
+
size = type.array_fixed_size
|
180
|
+
idx = type.array_length
|
181
|
+
|
182
|
+
if size <= 0
|
183
|
+
if idx > -1
|
184
|
+
size = @length_arg.retval
|
185
|
+
@length_arg.retval = nil
|
186
|
+
else
|
187
|
+
raise NotImplementedError
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
@postpost << "#{@retval} = GirFFI::ArgHelper.outptr_to_#{tag}_array #{@callarg}, #{size}"
|
192
|
+
|
193
|
+
if arg.ownership_transfer == :everything
|
194
|
+
if tag == :utf8
|
195
|
+
@postpost << "GirFFI::ArgHelper.cleanup_ptr_array_ptr #{@callarg}, #{rv}"
|
196
|
+
else
|
197
|
+
@postpost << "GirFFI::ArgHelper.cleanup_ptr_ptr #{@callarg}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def process_other_out_arg
|
203
|
+
tag = @arginfo.type.tag
|
204
|
+
@pre << "#{@callarg} = GirFFI::ArgHelper.#{tag}_outptr"
|
205
|
+
@post << "#{@retname} = GirFFI::ArgHelper.outptr_to_#{tag} #{@callarg}"
|
206
|
+
if @arginfo.ownership_transfer == :everything
|
207
|
+
@post << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
# Implements argument processing for arguments with direction :inout
|
214
|
+
class InOutArgumentBuilder < ArgumentBuilder
|
215
|
+
def prepare
|
216
|
+
@name = safe(@arginfo.name)
|
217
|
+
@callarg = @function_builder.new_var
|
218
|
+
@inarg = @name
|
219
|
+
@retname = @retval = @function_builder.new_var
|
220
|
+
end
|
221
|
+
|
222
|
+
def process
|
223
|
+
raise NotImplementedError unless @arginfo.ownership_transfer == :everything
|
224
|
+
|
225
|
+
case @arginfo.type.tag
|
226
|
+
when :interface
|
227
|
+
process_interface_inout_arg
|
228
|
+
when :array
|
229
|
+
process_array_inout_arg
|
230
|
+
else
|
231
|
+
process_other_inout_arg
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
private
|
236
|
+
|
237
|
+
def process_interface_inout_arg
|
238
|
+
raise NotImplementedError
|
239
|
+
end
|
240
|
+
|
241
|
+
def process_array_inout_arg
|
242
|
+
arg = @arginfo
|
243
|
+
tag = arg.type.param_type(0).tag
|
244
|
+
@pre << "#{@callarg} = GirFFI::ArgHelper.#{tag}_array_to_inoutptr #{@inarg}"
|
245
|
+
if arg.type.array_length > -1
|
246
|
+
idx = arg.type.array_length
|
247
|
+
rv = @length_arg.retval
|
248
|
+
@length_arg.retval = nil
|
249
|
+
lname = @length_arg.inarg
|
250
|
+
@length_arg.inarg = nil
|
251
|
+
@length_arg.pre.unshift "#{lname} = #{@inarg}.length"
|
252
|
+
@post << "#{@retval} = GirFFI::ArgHelper.outptr_to_#{tag}_array #{@callarg}, #{rv}"
|
253
|
+
if tag == :utf8
|
254
|
+
@post << "GirFFI::ArgHelper.cleanup_ptr_array_ptr #{@callarg}, #{rv}"
|
255
|
+
else
|
256
|
+
@post << "GirFFI::ArgHelper.cleanup_ptr_ptr #{@callarg}"
|
257
|
+
end
|
258
|
+
else
|
259
|
+
raise NotImplementedError
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def process_other_inout_arg
|
264
|
+
tag = @arginfo.type.tag
|
265
|
+
@pre << "#{@callarg} = GirFFI::ArgHelper.#{tag}_to_inoutptr #{@inarg}"
|
266
|
+
@post << "#{@retval} = GirFFI::ArgHelper.outptr_to_#{tag} #{@callarg}"
|
267
|
+
@post << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Implements argument processing for return values.
|
272
|
+
class ReturnValueBuilder < ArgumentBuilder
|
273
|
+
attr_reader :cvar
|
274
|
+
|
275
|
+
def prepare
|
276
|
+
return if tag == :void
|
277
|
+
@cvar = @function_builder.new_var
|
278
|
+
@retval = @function_builder.new_var
|
279
|
+
end
|
280
|
+
|
281
|
+
def process
|
282
|
+
return if tag == :void
|
283
|
+
|
284
|
+
type = @arginfo.return_type
|
285
|
+
|
286
|
+
case tag
|
287
|
+
when :interface
|
288
|
+
process_interface_return_value type, @cvar
|
289
|
+
when :array
|
290
|
+
process_array_return_value type, @cvar
|
291
|
+
else
|
292
|
+
process_other_return_value
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def type
|
297
|
+
@arginfo.return_type
|
298
|
+
end
|
299
|
+
|
300
|
+
private
|
301
|
+
|
302
|
+
def process_interface_return_value type, cvar
|
303
|
+
interface = type.interface
|
304
|
+
namespace = interface.namespace
|
305
|
+
name = interface.name
|
306
|
+
|
307
|
+
case interface.type
|
308
|
+
when :interface
|
309
|
+
GirFFI::Builder.build_class namespace, name
|
310
|
+
@post << "#{@retval} = ::#{namespace}::#{name}.wrap(#{cvar})"
|
311
|
+
when :object
|
312
|
+
if @arginfo.constructor?
|
313
|
+
GirFFI::Builder.build_class namespace, name
|
314
|
+
@post << "#{@retval} = ::#{namespace}::#{name}.wrap(#{cvar})"
|
315
|
+
if is_subclass_of_initially_unowned interface
|
316
|
+
@post << "GirFFI::GObject.object_ref_sink(#{@retval})"
|
317
|
+
end
|
318
|
+
else
|
319
|
+
@post << "#{@retval} = GirFFI::ArgHelper.object_pointer_to_object(#{cvar})"
|
320
|
+
end
|
321
|
+
when :struct
|
322
|
+
GirFFI::Builder.build_class namespace, name
|
323
|
+
@post << "#{@retval} = ::#{namespace}::#{name}.wrap(#{cvar})"
|
324
|
+
else
|
325
|
+
@post << "#{@retval} = #{cvar}"
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def process_array_return_value type, cvar
|
330
|
+
tag = type.param_type(0).tag
|
331
|
+
size = type.array_fixed_size
|
332
|
+
idx = type.array_length
|
333
|
+
|
334
|
+
if size > 0
|
335
|
+
@post << "#{@retval} = GirFFI::ArgHelper.ptr_to_#{tag}_array #{cvar}, #{size}"
|
336
|
+
elsif idx > -1
|
337
|
+
lendata = @length_arg #@data[idx]
|
338
|
+
rv = lendata.retval
|
339
|
+
lendata.retval = nil
|
340
|
+
@post << "#{@retval} = GirFFI::ArgHelper.ptr_to_#{tag}_array #{cvar}, #{rv}"
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
def process_other_return_value
|
345
|
+
@retval = @cvar
|
346
|
+
end
|
347
|
+
|
348
|
+
def tag
|
349
|
+
type.tag
|
350
|
+
end
|
351
|
+
|
352
|
+
def is_subclass_of_initially_unowned interface
|
353
|
+
if interface.namespace == "GObject" and interface.name == "InitiallyUnowned"
|
354
|
+
true
|
355
|
+
elsif interface.parent
|
356
|
+
is_subclass_of_initially_unowned interface.parent
|
357
|
+
else
|
358
|
+
false
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
# Implements argument processing for error handling arguments. These
|
364
|
+
# arguments are not part of the introspected signature, but their
|
365
|
+
# presence is indicated by the 'throws' attribute of the function.
|
366
|
+
class ErrorHandlerBuilder < ArgumentBuilder
|
367
|
+
def prepare
|
368
|
+
@callarg = @function_builder.new_var
|
369
|
+
end
|
370
|
+
|
371
|
+
def process
|
372
|
+
@pre << "#{@callarg} = FFI::MemoryPointer.new(:pointer).write_pointer nil"
|
373
|
+
@post << "GirFFI::ArgHelper.check_error(#{@callarg})"
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
# Argument builder that does nothing. Implements Null Object pattern.
|
378
|
+
class NullArgumentBuilder < ArgumentBuilder
|
379
|
+
def prepare; end
|
380
|
+
def process; end
|
381
|
+
end
|
382
|
+
end
|
data/lib/gir_ffi/builder.rb
CHANGED
@@ -30,8 +30,8 @@ module GirFFI
|
|
30
30
|
# All methods below will be made private at the end.
|
31
31
|
|
32
32
|
def self.ffi_function_argument_types info
|
33
|
-
types = info.args.map do |
|
34
|
-
tp = iarginfo_to_ffitype
|
33
|
+
types = info.args.map do |arg|
|
34
|
+
tp = iarginfo_to_ffitype arg
|
35
35
|
tp == :string ? :pointer : tp
|
36
36
|
end
|
37
37
|
if info.type == :function
|
@@ -93,8 +93,8 @@ module GirFFI
|
|
93
93
|
end
|
94
94
|
|
95
95
|
# Set up method access.
|
96
|
-
(self.public_methods - Module.public_methods).each do |
|
97
|
-
private_class_method
|
96
|
+
(self.public_methods - Module.public_methods).each do |method|
|
97
|
+
private_class_method method.to_sym
|
98
98
|
end
|
99
99
|
public_class_method :build_module, :build_class
|
100
100
|
public_class_method :itypeinfo_to_ffitype
|
@@ -37,15 +37,10 @@ module GirFFI
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def find_signal signal_name
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
info.interfaces.each do |i|
|
45
|
-
i.signals.each do |s|
|
46
|
-
return s if s.name == signal_name
|
47
|
-
end
|
48
|
-
end
|
40
|
+
signal_definers.each do |inf|
|
41
|
+
inf.signals.each do |sig|
|
42
|
+
return sig if sig.name == signal_name
|
43
|
+
end
|
49
44
|
end
|
50
45
|
if info.parent
|
51
46
|
return superclass.gir_ffi_builder.find_signal signal_name
|
@@ -57,14 +52,14 @@ module GirFFI
|
|
57
52
|
def build_class
|
58
53
|
unless defined? @klass
|
59
54
|
case info.type
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
55
|
+
when :object, :struct, :interface
|
56
|
+
instantiate_struct_class
|
57
|
+
when :union
|
58
|
+
instantiate_union_class
|
59
|
+
when :enum, :flags
|
60
|
+
instantiate_enum_class
|
61
|
+
else
|
62
|
+
raise NotImplementedError, "Cannot build classes of type #{info.type}"
|
68
63
|
end
|
69
64
|
end
|
70
65
|
@klass
|
@@ -118,7 +113,7 @@ module GirFFI
|
|
118
113
|
|
119
114
|
def instantiate_enum_class
|
120
115
|
@klass = optionally_define_constant namespace_module, @classname do
|
121
|
-
vals = info.values.map {|
|
116
|
+
vals = info.values.map {|vinfo| [vinfo.name.to_sym, vinfo.value]}.flatten
|
122
117
|
lib.enum(@classname.to_sym, vals)
|
123
118
|
end
|
124
119
|
end
|
@@ -139,7 +134,11 @@ module GirFFI
|
|
139
134
|
end
|
140
135
|
|
141
136
|
def layout_specification
|
142
|
-
fields = info.
|
137
|
+
fields = if info.type == :interface
|
138
|
+
[]
|
139
|
+
else
|
140
|
+
info.fields
|
141
|
+
end
|
143
142
|
|
144
143
|
if fields.empty?
|
145
144
|
if parent
|
@@ -149,10 +148,10 @@ module GirFFI
|
|
149
148
|
end
|
150
149
|
end
|
151
150
|
|
152
|
-
fields.map do |
|
153
|
-
[
|
154
|
-
itypeinfo_to_ffitype_for_struct(
|
155
|
-
|
151
|
+
fields.map do |finfo|
|
152
|
+
[ finfo.name.to_sym,
|
153
|
+
itypeinfo_to_ffitype_for_struct(finfo.type),
|
154
|
+
finfo.offset ]
|
156
155
|
end.flatten
|
157
156
|
end
|
158
157
|
|
@@ -168,14 +167,14 @@ module GirFFI
|
|
168
167
|
end
|
169
168
|
|
170
169
|
def stub_methods
|
171
|
-
info.methods.each do |
|
172
|
-
@klass.class_eval method_stub(
|
170
|
+
info.methods.each do |minfo|
|
171
|
+
@klass.class_eval method_stub(minfo.name, minfo.method?)
|
173
172
|
end
|
174
173
|
end
|
175
174
|
|
176
|
-
def method_stub
|
175
|
+
def method_stub symbol, is_instance_method
|
177
176
|
"
|
178
|
-
def #{
|
177
|
+
def #{is_instance_method ? '' : 'self.'}#{symbol} *args, &block
|
179
178
|
setup_and_call :#{symbol}, *args, &block
|
180
179
|
end
|
181
180
|
"
|
@@ -193,13 +192,13 @@ module GirFFI
|
|
193
192
|
end
|
194
193
|
|
195
194
|
def setup_vfunc_invokers
|
196
|
-
info.vfuncs.each do |
|
197
|
-
invoker =
|
195
|
+
info.vfuncs.each do |vfinfo|
|
196
|
+
invoker = vfinfo.invoker
|
198
197
|
next if invoker.nil?
|
199
|
-
next if invoker.name ==
|
198
|
+
next if invoker.name == vfinfo.name
|
200
199
|
|
201
200
|
@klass.class_eval "
|
202
|
-
def #{
|
201
|
+
def #{vfinfo.name} *args, &block
|
203
202
|
#{invoker.name}(*args, &block)
|
204
203
|
end
|
205
204
|
"
|
@@ -228,8 +227,8 @@ module GirFFI
|
|
228
227
|
end
|
229
228
|
|
230
229
|
def instance_method_introspection_data method
|
231
|
-
|
232
|
-
return !
|
230
|
+
data = method_introspection_data method
|
231
|
+
return !data.nil? && data.method? ? data : nil
|
233
232
|
end
|
234
233
|
|
235
234
|
def function_definition go
|
@@ -257,5 +256,9 @@ module GirFFI
|
|
257
256
|
Class.new parent
|
258
257
|
}
|
259
258
|
end
|
259
|
+
|
260
|
+
def signal_definers
|
261
|
+
[info] + (info.type == :object ? info.interfaces : [])
|
262
|
+
end
|
260
263
|
end
|
261
264
|
end
|