gir_ffi 0.4.2 → 0.4.3

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 CHANGED
@@ -1,3 +1,9 @@
1
+ == 0.4.3 / 2012-11-02
2
+
3
+ * Remove gobject-introspection version check
4
+ * Make tests pass with gobject-introspection 1.34
5
+ * Ongoing refactoring
6
+
1
7
  == 0.4.2 / 2012-09-22
2
8
 
3
9
  * Make objects and interfaces wrap poiners in the class that matches
@@ -0,0 +1,22 @@
1
+ module GLib
2
+ # Extra methods for GLib::Strv.
3
+ class Strv
4
+ def self.from it
5
+ case it
6
+ when nil
7
+ nil
8
+ when FFI::Pointer
9
+ wrap it
10
+ when self
11
+ it
12
+ else
13
+ from_enumerable it
14
+ end
15
+ end
16
+
17
+ def self.from_enumerable enum
18
+ self.wrap GirFFI::InPointer.from_array :utf8, enum
19
+ end
20
+ end
21
+ end
22
+
data/lib/ffi-glib.rb CHANGED
@@ -9,6 +9,7 @@ require 'ffi-glib/hash_table'
9
9
  require 'ffi-glib/byte_array'
10
10
  require 'ffi-glib/array'
11
11
  require 'ffi-glib/ptr_array'
12
+ require 'ffi-glib/strv'
12
13
 
13
14
  module GLib
14
15
  # @deprecated Compatibility function. Remove in version 0.5.0.
@@ -2,7 +2,14 @@ module GObjectIntrospection
2
2
  # Wraps a GIConstantInfo struct; represents an constant.
3
3
  class IConstantInfo < IBaseInfo
4
4
  TYPE_TAG_TO_UNION_MEMBER = {
5
+ :gint8 => :v_int8,
6
+ :gint16 => :v_int16,
5
7
  :gint32 => :v_int32,
8
+ :gint64 => :v_int64,
9
+ :guint8 => :v_uint8,
10
+ :guint16 => :v_uint16,
11
+ :guint32 => :v_uint32,
12
+ :guint64 => :v_uint64,
6
13
  :gdouble => :v_double,
7
14
  :utf8 => :v_string
8
15
  }
@@ -3,19 +3,7 @@ require 'ffi'
3
3
  module GObjectIntrospection
4
4
  module Lib
5
5
  extend FFI::Library
6
- begin
7
- ffi_lib "girepository-1.0.so.1"
8
- rescue LoadError
9
- begin
10
- ffi_lib "girepository-1.0.so.0"
11
- warn "This old version of gobject-introspection is not supported by GirFFI."
12
- warn "Please upgrade to at least version 0.10.0."
13
- rescue LoadError
14
- ffi_lib "girepository-1.0"
15
- warn "This platform and/or version of gobject-introspection are not supported by GirFFI."
16
- warn "Please file bugs for any errors found."
17
- end
18
- end
6
+ ffi_lib "girepository-1.0"
19
7
 
20
8
  # IRepository
21
9
  enum :IRepositoryLoadFlags, [:LAZY, (1<<0)]
@@ -1,3 +1,5 @@
1
+ require 'gir_ffi/info_ext/i_registered_type_info'
2
+
1
3
  module GirFFI
2
4
  module Builder
3
5
  module Argument
@@ -17,7 +19,7 @@ module GirFFI
17
19
 
18
20
  attr_accessor :length_arg, :array_arg
19
21
 
20
- def initialize var_gen, name, typeinfo
22
+ def initialize var_gen, name, typeinfo, direction
21
23
  @typeinfo = typeinfo
22
24
  @inarg = nil
23
25
  @retname = nil
@@ -35,6 +37,14 @@ module GirFFI
35
37
  type_info.tag
36
38
  end
37
39
 
40
+ def specialized_type_tag
41
+ type_info.flattened_tag
42
+ end
43
+
44
+ def type_specification
45
+ type_info.type_specification
46
+ end
47
+
38
48
  TAG_TO_WRAPPER_CLASS_MAP = {
39
49
  :glist => 'GLib::List',
40
50
  :gslist => 'GLib::SList',
@@ -47,14 +57,25 @@ module GirFFI
47
57
  def argument_class_name
48
58
  case (tag = type_tag)
49
59
  when :interface
50
- iface = type_info.interface
51
- # FIXME: Extract to ITypeInfo.
52
- "::#{iface.safe_namespace}::#{iface.name}"
60
+ type_info.interface_type_name
53
61
  when :array
54
- if type_info.zero_terminated?
55
- 'GLib::Strv'
56
- else
62
+ case type_info.array_type
63
+ when :byte_array
64
+ 'GLib::ByteArray'
65
+ when :array
57
66
  'GLib::Array'
67
+ when :ptr_array
68
+ 'GLib::PtrArray'
69
+ else # :c
70
+ if type_info.zero_terminated?
71
+ if type_info.element_type == :utf8
72
+ 'GLib::Strv'
73
+ else
74
+ 'GirFFI::InPointer'
75
+ end
76
+ else
77
+ 'GirFFI::InPointer'
78
+ end
58
79
  end
59
80
  else
60
81
  TAG_TO_WRAPPER_CLASS_MAP[tag]
@@ -65,8 +86,7 @@ module GirFFI
65
86
  type = type_info.param_type(index)
66
87
  tag = type.tag
67
88
  base = if tag == :interface
68
- iface = type.interface
69
- "::#{iface.safe_namespace}::#{iface.name}"
89
+ type.interface_type_name
70
90
  else
71
91
  tag.inspect
72
92
  end
@@ -4,12 +4,11 @@ module GirFFI
4
4
  # Abstract base class implementing argument processing for arguments
5
5
  # with direction :in.
6
6
  class InBase < Base
7
- def initialize var_gen, name, typeinfo
8
- super var_gen, name, typeinfo
7
+ def initialize var_gen, name, typeinfo, direction
8
+ super var_gen, name, typeinfo, direction
9
9
  @inarg = @name
10
10
  end
11
11
  end
12
12
  end
13
13
  end
14
14
  end
15
-
@@ -4,8 +4,8 @@ module GirFFI
4
4
  # Abstract base class implementing argument processing for arguments
5
5
  # with direction :inout.
6
6
  class InOutBase < Base
7
- def initialize var_gen, name, typeinfo
8
- super var_gen, name, typeinfo
7
+ def initialize var_gen, name, typeinfo, direction
8
+ super var_gen, name, typeinfo, direction
9
9
  @inarg = @name
10
10
  end
11
11
 
@@ -16,6 +16,3 @@ module GirFFI
16
16
  end
17
17
  end
18
18
  end
19
-
20
-
21
-
@@ -22,28 +22,22 @@ module GirFFI::Builder
22
22
  module InArgument
23
23
  def self.build var_gen, arginfo, libmodule
24
24
  type = arginfo.argument_type
25
- builder_for var_gen, arginfo.name, type, libmodule
25
+ builder_for var_gen, arginfo.name, type, arginfo.direction, libmodule
26
26
  end
27
27
 
28
- def self.builder_for var_gen, name, type, libmodule
28
+ def self.builder_for var_gen, name, type, direction, libmodule
29
29
  klass = case type.tag
30
30
  when :interface
31
31
  case type.interface.info_type
32
32
  when :callback
33
33
  return CallbackInArgument.new var_gen, name, type, libmodule
34
34
  else
35
- RegularInArgument
36
- end
37
- when :array
38
- if type.array_type == :c
39
- CArrayInArgument
40
- else
41
- RegularInArgument
35
+ RegularArgument
42
36
  end
43
37
  else
44
- RegularInArgument
38
+ RegularArgument
45
39
  end
46
- return klass.new var_gen, name, type
40
+ return klass.new var_gen, name, type, direction
47
41
  end
48
42
  end
49
43
 
@@ -51,7 +45,7 @@ module GirFFI::Builder
51
45
  # :in.
52
46
  class CallbackInArgument < Argument::InBase
53
47
  def initialize var_gen, name, type, libmodule
54
- super var_gen, name, type
48
+ super var_gen, name, type, :in
55
49
  @libmodule = libmodule
56
50
  end
57
51
 
@@ -62,19 +56,6 @@ module GirFFI::Builder
62
56
  end
63
57
  end
64
58
 
65
- # Implements argument processing for array arguments with direction :in.
66
- class CArrayInArgument < Argument::InBase
67
- def pre
68
- pr = []
69
- size = type_info.array_fixed_size
70
- if size > -1
71
- pr << "GirFFI::ArgHelper.check_fixed_array_size #{size}, #{@name}, \"#{@name}\""
72
- end
73
- pr << "#{callarg} = GirFFI::InPointer.from_array #{elm_t}, #{@name}"
74
- pr
75
- end
76
- end
77
-
78
59
  # Implements argument processing for arguments with direction :in whose
79
60
  # type-specific processing is left to FFI (e.g., ints and floats, and
80
61
  # objects that implement to_ptr.).
@@ -87,38 +68,160 @@ module GirFFI::Builder
87
68
  #
88
69
  # Implements argument processing for void pointer arguments with
89
70
  # direction :in.
90
- class RegularInArgument < Argument::InBase
71
+ #
72
+ # Implements argument processing for interface arguments with direction
73
+ # :inout (structs, objects, etc.).
74
+ #
75
+ # Implements argument processing for arguments with direction
76
+ # :out that are neither arrays nor 'interfaces'.
77
+ class RegularArgument < Argument::Base
78
+ def initialize var_gen, name, typeinfo, direction
79
+ super var_gen, name, typeinfo, direction
80
+ @direction = direction
81
+ end
82
+
83
+ def inarg
84
+ if has_input_value?
85
+ @array_arg.nil? ? @name : nil
86
+ end
87
+ end
88
+
89
+ def retname
90
+ if has_output_value?
91
+ @retname ||= @var_gen.new_var
92
+ end
93
+ end
94
+
91
95
  def pre
92
96
  pr = []
93
- assign_array_length(pr)
94
- set_function_call_argument(pr)
97
+ if has_input_value?
98
+ pr << fixed_array_size_check if needs_size_check?
99
+ pr << array_length_assignment if is_array_length_parameter?
100
+ end
101
+ pr << set_function_call_argument
95
102
  pr
96
103
  end
97
104
 
98
- def assign_array_length(pr)
99
- if @array_arg
100
- arrname = @array_arg.name
101
- pr << "#{@name} = #{arrname}.nil? ? 0 : #{arrname}.length"
105
+ def post
106
+ result = []
107
+ if has_output_value?
108
+ value = case @direction
109
+ when :inout
110
+ "#{argument_class_name}.wrap(#{output_conversion_arguments})"
111
+ when :out
112
+ "#{callarg}.to_value"
113
+ end
114
+ result << "#{retname} = #{value}"
115
+ end
116
+ result
117
+ end
118
+
119
+ private
120
+
121
+ def is_array_length_parameter?
122
+ @array_arg
123
+ end
124
+
125
+ def needs_size_check?
126
+ if type_tag == :array
127
+ size = type_info.array_fixed_size
128
+ if size > -1
129
+ true
130
+ end
102
131
  end
103
132
  end
104
133
 
105
- def set_function_call_argument(pr)
106
- if type_tag == :interface && [:object, :struct].include?(type_info.interface.info_type)
107
- pr << "#{callarg} = #{argument_class_name}.from #{@name}"
108
- elsif [:utf8, :void].include? type_tag
109
- pr << "#{callarg} = #{argument_class_name}.from #{type_tag.inspect}, #{@name}"
110
- elsif [:glist, :gslist, :ghash].include? type_tag
111
- pr << "#{callarg} = #{argument_class_name}.from #{elm_t}, #{@name}"
134
+ def fixed_array_size_check
135
+ size = type_info.array_fixed_size
136
+ "GirFFI::ArgHelper.check_fixed_array_size #{size}, #{@name}, \"#{@name}\""
137
+ end
138
+
139
+ def has_output_value?
140
+ @direction == :inout || @direction == :out
141
+ end
142
+
143
+ def has_input_value?
144
+ @direction == :inout || @direction == :in
145
+ end
146
+
147
+ def array_length_assignment
148
+ arrname = @array_arg.name
149
+ "#{@name} = #{arrname}.nil? ? 0 : #{arrname}.length"
150
+ end
151
+
152
+ def set_function_call_argument
153
+ value = if @direction == :out
154
+ "GirFFI::InOutPointer.for #{type_tag.inspect}"
155
+ else
156
+ if needs_ingoing_parameter_conversion?
157
+ parameter_conversion
158
+ else
159
+ @name
160
+ end
161
+ end
162
+ "#{callarg} = #{value}"
163
+ end
164
+
165
+ def needs_outgoing_parameter_conversion?
166
+ case specialized_type_tag
167
+ when :object, :struct, :utf8, :void, :glist, :gslist, :ghash, :array, :c, :strv
168
+ true
169
+ else
170
+ false
171
+ end
172
+ end
173
+
174
+ def needs_ingoing_parameter_conversion?
175
+ case specialized_type_tag
176
+ when :object, :struct, :utf8, :void, :glist, :gslist, :ghash, :array, :c, :strv
177
+ true
178
+ else
179
+ false
180
+ end
181
+ end
182
+
183
+ def parameter_conversion
184
+ base = "#{argument_class_name}.from(#{parameter_conversion_arguments})"
185
+ if has_output_value?
186
+ "GirFFI::InOutPointer.from :pointer, #{base}"
112
187
  else
113
- pr << "#{callarg} = #{@name}"
188
+ base
114
189
  end
115
190
  end
191
+
192
+ def output_conversion_arguments
193
+ conversion_arguments "#{callarg}.to_value"
194
+ end
195
+
196
+ def parameter_conversion_arguments
197
+ conversion_arguments @name
198
+ end
199
+
200
+ def conversion_arguments name
201
+ case specialized_type_tag
202
+ when :utf8, :void
203
+ "#{self_t}, #{name}"
204
+ when :glist, :gslist, :ghash, :array
205
+ "#{elm_t}, #{name}"
206
+ when :c
207
+ "#{type_specification}, #{name}"
208
+ when :strv
209
+ "#{name}"
210
+ else
211
+ "#{name}"
212
+ end
213
+ end
214
+
215
+ def self_t
216
+ type_tag.inspect
217
+ end
116
218
  end
117
219
 
118
220
  # Implements argument processing for arguments with direction :out.
119
221
  module OutArgument
120
222
  def self.build var_gen, arginfo, libmodule
121
223
  type = arginfo.argument_type
224
+ direction = arginfo.direction
122
225
  klass = case type.tag
123
226
  when :interface
124
227
  case type.interface.info_type
@@ -139,35 +242,19 @@ module GirFFI::Builder
139
242
  when :c
140
243
  CArrayOutArgument
141
244
  when :array
142
- it = PointerLikeOutArgument.new var_gen, arginfo.name, type
245
+ it = PointerLikeOutArgument.new var_gen, arginfo.name, type, direction
143
246
  it.extend WithTypedContainerPostMethod
144
247
  return it
145
248
  end
146
249
  end
147
- when :glist, :gslist
148
- it = PointerLikeOutArgument.new var_gen, arginfo.name, type
149
- it.extend WithTypedContainerPostMethod
150
- return it
151
- when :ghash
152
- it = PointerLikeOutArgument.new var_gen, arginfo.name, type
250
+ when :glist, :gslist, :ghash
251
+ it = PointerLikeOutArgument.new var_gen, arginfo.name, type, direction
153
252
  it.extend WithTypedContainerPostMethod
154
253
  return it
155
254
  else
156
- RegularOutArgument
255
+ RegularArgument
157
256
  end
158
- klass.new var_gen, arginfo.name, type
159
- end
160
- end
161
-
162
- # Implements argument processing for arguments with direction
163
- # :out that are neither arrays nor 'interfaces'.
164
- class RegularOutArgument < Argument::OutBase
165
- def pre
166
- [ "#{callarg} = GirFFI::InOutPointer.for #{type_tag.inspect}" ]
167
- end
168
-
169
- def post
170
- [ "#{retname} = #{callarg}.to_value" ]
257
+ klass.new var_gen, arginfo.name, type, direction
171
258
  end
172
259
  end
173
260
 
@@ -237,13 +324,14 @@ module GirFFI::Builder
237
324
  module InOutArgument
238
325
  def self.build var_gen, arginfo, libmodule
239
326
  type = arginfo.argument_type
327
+ direction = arginfo.direction
240
328
  klass = case type.tag
241
329
  when :interface
242
330
  case type.interface.info_type
243
331
  when :enum, :flags
244
332
  EnumInOutArgument
245
333
  else
246
- InterfaceInOutArgument
334
+ RegularArgument
247
335
  end
248
336
  when :array
249
337
  if type.zero_terminated?
@@ -253,27 +341,16 @@ module GirFFI::Builder
253
341
  when :c
254
342
  CArrayInOutArgument
255
343
  when :array
256
- it = Argument::InOutBase.new var_gen, arginfo.name, type
257
- it.extend WithTypedContainerInOutPreMethod
258
- it.extend WithTypedContainerPostMethod
259
- return it
344
+ RegularArgument
260
345
  end
261
346
  end
262
- when :glist, :gslist
263
- it = Argument::InOutBase.new var_gen, arginfo.name, type
264
- it.extend WithTypedContainerInOutPreMethod
265
- it.extend WithTypedContainerPostMethod
266
- return it
267
- when :ghash
268
- it = Argument::InOutBase.new var_gen, arginfo.name, type
269
- it.extend WithTypedContainerInOutPreMethod
270
- it.extend WithTypedContainerPostMethod
271
- return it
347
+ when :glist, :gslist, :ghash
348
+ RegularArgument
272
349
  else
273
350
  RegularInOutArgument
274
351
  end
275
352
 
276
- klass.new var_gen, arginfo.name, type
353
+ klass.new var_gen, arginfo.name, type, direction
277
354
  end
278
355
  end
279
356
 
@@ -291,23 +368,11 @@ module GirFFI::Builder
291
368
  end
292
369
  end
293
370
 
294
- # Implements argument processing for interface arguments with direction
295
- # :inout (structs, objects, etc.).
296
- class InterfaceInOutArgument < Argument::InOutBase
297
- def pre
298
- [ "#{callarg} = GirFFI::InOutPointer.from :pointer, #{argument_class_name}.from(#{@name}).to_ptr" ]
299
- end
300
-
301
- def post
302
- [ "#{retname} = #{argument_class_name}.wrap(#{callarg}.to_value)" ]
303
- end
304
- end
305
-
306
371
  # Implements argument processing for strv arguments with direction
307
372
  # :inout.
308
373
  class StrvInOutArgument < Argument::InOutBase
309
374
  def pre
310
- [ "#{callarg} = GirFFI::InOutPointer.from_array #{elm_t}, #{@name}" ]
375
+ [ "#{callarg} = GirFFI::InOutPointer.from #{type_specification}, #{@name}" ]
311
376
  end
312
377
 
313
378
  def post
@@ -329,12 +394,6 @@ module GirFFI::Builder
329
394
  end
330
395
  end
331
396
 
332
- module WithTypedContainerInOutPreMethod
333
- def pre
334
- [ "#{callarg} = GirFFI::InOutPointer.from :pointer, #{argument_class_name}.from(#{elm_t}, #{@name})" ]
335
- end
336
- end
337
-
338
397
  # Implements argument processing for arguments with direction
339
398
  # :inout that are neither arrays nor 'interfaces'.
340
399
  class RegularInOutArgument < Argument::InOutBase
@@ -357,24 +416,25 @@ module GirFFI::Builder
357
416
  builder_for(var_gen,
358
417
  arginfo.name,
359
418
  arginfo.return_type,
419
+ :return,
360
420
  arginfo.constructor?)
361
421
  end
362
422
 
363
- def self.builder_for var_gen, name, type, is_constructor
423
+ def self.builder_for var_gen, name, type, direction, is_constructor
364
424
  if type.tag == :interface and
365
425
  [:interface, :object].include? type.interface.info_type
366
426
  klass = if is_constructor
367
427
  ConstructorReturnValue
368
428
  else
369
- ObjectReturnValue
429
+ WrappingReturnValue
370
430
  end
371
- klass.new var_gen, name, type
431
+ klass.new var_gen, name, type, direction
372
432
  else
373
- builder_for_field_getter var_gen, name, type
433
+ builder_for_field_getter var_gen, name, type, direction
374
434
  end
375
435
  end
376
436
 
377
- def self.builder_for_field_getter var_gen, name, type
437
+ def self.builder_for_field_getter var_gen, name, type, direction
378
438
  klass = case type.tag
379
439
  when :void
380
440
  if type.pointer?
@@ -385,33 +445,27 @@ module GirFFI::Builder
385
445
  when :interface
386
446
  case type.interface.info_type
387
447
  when :struct, :union, :interface, :object
388
- InterfaceReturnValue
448
+ WrappingReturnValue
389
449
  else
390
450
  RegularReturnValue
391
451
  end
392
452
  when :array
393
453
  if type.zero_terminated?
394
- StrvReturnValue
454
+ WrappingReturnValue
395
455
  else
396
456
  case type.array_type
397
457
  when :c
398
458
  CArrayReturnValue
399
459
  when :array
400
- it = ReturnValue.new var_gen, name, type
460
+ it = ReturnValue.new var_gen, name, type, direction
401
461
  it.extend WithTypedContainerPostMethod
402
462
  return it
403
- when :byte_array
404
- ByteArrayReturnValue
405
463
  else
406
- PtrArrayReturnValue
464
+ WrappingReturnValue
407
465
  end
408
466
  end
409
- when :glist, :gslist
410
- it = ReturnValue.new var_gen, name, type
411
- it.extend WithTypedContainerPostMethod
412
- return it
413
- when :ghash
414
- it = ReturnValue.new var_gen, name, type
467
+ when :glist, :gslist, :ghash
468
+ it = ReturnValue.new var_gen, name, type, direction
415
469
  it.extend WithTypedContainerPostMethod
416
470
  return it
417
471
  when :utf8
@@ -419,7 +473,7 @@ module GirFFI::Builder
419
473
  else
420
474
  RegularReturnValue
421
475
  end
422
- klass.new var_gen, name, type
476
+ klass.new var_gen, name, type, direction
423
477
  end
424
478
  end
425
479
 
@@ -447,14 +501,16 @@ module GirFFI::Builder
447
501
  # Implements argument processing for interface return values (interfaces
448
502
  # and structs, but not objects, which need special handling for
449
503
  # polymorphism and constructors).
450
- class InterfaceReturnValue < ReturnValue
451
- def post
452
- [ "#{retname} = #{argument_class_name}.wrap(#{cvar})" ]
453
- end
454
- end
455
-
456
- # Implements argument processing for object return values.
457
- class ObjectReturnValue < ReturnValue
504
+ #
505
+ # Implements argument processing for object return values when the method is
506
+ # not a constructor.
507
+ #
508
+ # Implements argument processing for NULL-terminated string array return values.
509
+ #
510
+ # Implements argument processing for GByteArray return values.
511
+ #
512
+ # Implements argument processing for GPtrArray return values.
513
+ class WrappingReturnValue < ReturnValue
458
514
  def post
459
515
  [ "#{retname} = #{argument_class_name}.wrap(#{cvar})" ]
460
516
  end
@@ -476,13 +532,6 @@ module GirFFI::Builder
476
532
  end
477
533
  end
478
534
 
479
- # Implements argument processing for NULL-terminated string array return values.
480
- class StrvReturnValue < ReturnValue
481
- def post
482
- [ "#{retname} = GLib::Strv.wrap(#{cvar})" ]
483
- end
484
- end
485
-
486
535
  # Implements argument processing for UTF8 string return values.
487
536
  class Utf8ReturnValue < ReturnValue
488
537
  def post
@@ -490,20 +539,6 @@ module GirFFI::Builder
490
539
  end
491
540
  end
492
541
 
493
- # Implements argument processing for GByteArray return values.
494
- class ByteArrayReturnValue < ReturnValue
495
- def post
496
- [ "#{retname} = GLib::ByteArray.wrap(#{cvar})" ]
497
- end
498
- end
499
-
500
- # Implements argument processing for GPtrArray return values.
501
- class PtrArrayReturnValue < ReturnValue
502
- def post
503
- [ "#{retname} = GLib::PtrArray.wrap(#{cvar})" ]
504
- end
505
- end
506
-
507
542
  # Implements argument processing for other return values.
508
543
  class RegularReturnValue < ReturnValue
509
544
  def retval
@@ -45,13 +45,13 @@ module GirFFI
45
45
 
46
46
  def return_value_builder
47
47
  @rv_builder ||= ReturnValueFactory.builder_for_field_getter(
48
- VariableNameGenerator.new, @info.name, @info.field_type)
48
+ VariableNameGenerator.new, @info.name, @info.field_type, :return)
49
49
  end
50
50
 
51
51
  def setter_builder
52
52
  type = @info.field_type
53
53
  vargen = VariableNameGenerator.new
54
- Builder::InArgument.builder_for vargen, "value", type, @libmodule
54
+ Builder::InArgument.builder_for vargen, "value", type, :in, @libmodule
55
55
  end
56
56
  end
57
57
  end
@@ -37,7 +37,7 @@ module GirFFI::Builder
37
37
 
38
38
  def setup_error_argument vargen
39
39
  klass = @info.throws? ? ErrorArgument : NullArgument
40
- @errarg = klass.new vargen, nil, nil
40
+ @errarg = klass.new vargen, nil, nil, :error
41
41
  end
42
42
 
43
43
  def filled_out_template
@@ -26,19 +26,6 @@ module GirFFI
26
26
  ArgHelper.ptr_to_typed_array @sub_type, block, size
27
27
  end
28
28
 
29
- private
30
-
31
- def adjust_value_out value
32
- case @value_type
33
- when :gboolean
34
- (value != 0)
35
- when :utf8
36
- ArgHelper.ptr_to_utf8 value
37
- else
38
- value
39
- end
40
- end
41
-
42
29
  def self.for type, sub_type=nil
43
30
  ffi_type = TypeMap.map_basic_type_or_string type
44
31
  ptr = AllocationHelper.safe_malloc(FFI.type_size ffi_type)
@@ -47,6 +34,11 @@ module GirFFI
47
34
  end
48
35
 
49
36
  def self.from type, value, sub_type=nil
37
+ if Array === type
38
+ arr_t, sub_t = *type
39
+ # TODO: Take array type into account (zero-terminated or not)
40
+ return self.from_array sub_t, value
41
+ end
50
42
  value = adjust_value_in type, value
51
43
  ffi_type = TypeMap.map_basic_type_or_string type
52
44
  ptr = AllocationHelper.safe_malloc(FFI.type_size ffi_type)
@@ -85,6 +77,20 @@ module GirFFI
85
77
  end
86
78
  end
87
79
  end
80
+
81
+ private
82
+
83
+ def adjust_value_out value
84
+ case @value_type
85
+ when :gboolean
86
+ (value != 0)
87
+ when :utf8
88
+ ArgHelper.ptr_to_utf8 value
89
+ else
90
+ value
91
+ end
92
+ end
93
+
88
94
  end
89
95
  end
90
96
 
@@ -18,6 +18,10 @@ module GirFFI
18
18
  def self.from type, val
19
19
  return nil if val.nil?
20
20
  case type
21
+ when Array
22
+ arr_t, sub_t = *type
23
+ # TODO: Take array type into account (zero-terminated or not)
24
+ self.from_array sub_t, val
21
25
  when :utf8, :filename
22
26
  from_utf8 val
23
27
  when :gint32, :gint8
@@ -0,0 +1,14 @@
1
+ require 'gir_ffi/builder_helper'
2
+
3
+ module GirFFI
4
+ module InfoExt
5
+ module IRegisteredTypeInfo
6
+ def full_type_name
7
+ "::#{safe_namespace}::#{name}"
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ GObjectIntrospection::IRegisteredTypeInfo.send :include, GirFFI::InfoExt::IRegisteredTypeInfo
14
+
@@ -24,6 +24,61 @@ module GirFFI
24
24
  end
25
25
  end
26
26
 
27
+ def element_type
28
+ case tag
29
+ when :glist, :gslist, :array
30
+ subtype_tag 0
31
+ when :ghash
32
+ [subtype_tag(0), subtype_tag(1)]
33
+ else
34
+ nil
35
+ end
36
+ end
37
+
38
+ def interface_type_name
39
+ interface.full_type_name
40
+ end
41
+
42
+ def type_specification
43
+ tag = self.tag
44
+ if tag == :array
45
+ "[#{flattened_array_type.inspect}, #{element_type.inspect}]"
46
+ else
47
+ tag.inspect
48
+ end
49
+ end
50
+
51
+ def flattened_tag
52
+ case tag
53
+ when :interface
54
+ interface_type
55
+ when :array
56
+ flattened_array_type
57
+ else
58
+ tag
59
+ end
60
+ end
61
+
62
+ def interface_type
63
+ interface.info_type
64
+ end
65
+
66
+ def flattened_array_type
67
+ if zero_terminated?
68
+ if element_type == :utf8
69
+ :strv
70
+ else
71
+ # TODO: Check that array_type == :c
72
+ # TODO: Perhaps distinguish :c from zero-terminated :c
73
+ :c
74
+ end
75
+ else
76
+ array_type
77
+ end
78
+ end
79
+
80
+ private
81
+
27
82
  def subtype_tag index
28
83
  st = param_type(index)
29
84
  tag = st.tag
@@ -38,17 +93,6 @@ module GirFFI
38
93
  return tag
39
94
  end
40
95
  end
41
-
42
- def element_type
43
- case tag
44
- when :glist, :gslist, :array
45
- subtype_tag 0
46
- when :ghash
47
- [subtype_tag(0), subtype_tag(1)]
48
- else
49
- nil
50
- end
51
- end
52
96
  end
53
97
  end
54
98
  end
@@ -1,4 +1,4 @@
1
1
  module GirFFI
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.3"
3
3
  end
4
4
 
@@ -9,7 +9,7 @@ describe GirFFI::Builder::Argument::Base do
9
9
 
10
10
  mock(info = Object.new).param_type(0) { subtype }
11
11
 
12
- builder = GirFFI::Builder::Argument::Base.new nil, 'foo', info
12
+ builder = GirFFI::Builder::Argument::Base.new nil, 'foo', info, :direction
13
13
  assert_equal ":void", builder.subtype_tag_or_class_name
14
14
  end
15
15
  end
@@ -21,24 +21,21 @@ describe GirFFI::Builder::Argument::Base do
21
21
 
22
22
  mock(info = Object.new).param_type(0) { subtype }
23
23
 
24
- builder = GirFFI::Builder::Argument::Base.new nil, 'bar', info
24
+ builder = GirFFI::Builder::Argument::Base.new nil, 'bar', info, :direction
25
25
  assert_equal ":foo", builder.subtype_tag_or_class_name
26
26
  end
27
27
  end
28
28
 
29
- describe "for an array of interface class Foo::Bar" do
30
- it "returns the string '::Foo::Bar'" do
31
- mock(interface = Object.new).safe_namespace { "Foo" }
32
- mock(interface).name { "Bar" }
33
-
29
+ describe "for an array of an interface class" do
30
+ it "returns the interface's full class name" do
34
31
  mock(subtype = Object.new).tag { :interface }
35
- mock(subtype).interface { interface }
32
+ mock(subtype).interface_type_name { "-full-type-name-" }
36
33
  mock(subtype).pointer? { false }
37
34
 
38
35
  mock(info = Object.new).param_type(0) { subtype }
39
36
 
40
- builder = GirFFI::Builder::Argument::Base.new nil, 'bar', info
41
- assert_equal "::Foo::Bar", builder.subtype_tag_or_class_name
37
+ builder = GirFFI::Builder::Argument::Base.new nil, 'bar', info, :direction
38
+ assert_equal "-full-type-name-", builder.subtype_tag_or_class_name
42
39
  end
43
40
  end
44
41
 
@@ -49,11 +46,10 @@ describe GirFFI::Builder::Argument::Base do
49
46
 
50
47
  mock(info = Object.new).param_type(0) { subtype }
51
48
 
52
- builder = GirFFI::Builder::Argument::Base.new nil, 'bar', info
49
+ builder = GirFFI::Builder::Argument::Base.new nil, 'bar', info, :direction
53
50
  assert_equal "[:pointer, :foo]", builder.subtype_tag_or_class_name
54
51
  end
55
52
  end
56
-
57
53
  end
58
54
  end
59
55
 
@@ -38,7 +38,7 @@ describe GirFFI::Builder::Function do
38
38
  def self.test_array_gint16_in ints
39
39
  n_ints = ints.nil? ? 0 : ints.length
40
40
  _v1 = n_ints
41
- _v2 = GirFFI::InPointer.from_array :gint16, ints
41
+ _v2 = GirFFI::InPointer.from([:c, :gint16], ints)
42
42
  _v3 = DummyLib.regress_test_array_gint16_in _v1, _v2
43
43
  return _v3
44
44
  end
@@ -56,7 +56,7 @@ describe GirFFI::Builder::Function do
56
56
  def self.test_callback_destroy_notify callback, user_data, notify
57
57
  _v1 = GirFFI::CallbackHelper.wrap_in_callback_args_mapper \"Regress\", \"TestCallbackUserData\", callback
58
58
  DummyLib::CALLBACKS << _v1
59
- _v2 = GirFFI::InPointer.from :void, user_data
59
+ _v2 = GirFFI::InPointer.from(:void, user_data)
60
60
  _v3 = GirFFI::CallbackHelper.wrap_in_callback_args_mapper \"GLib\", \"DestroyNotify\", notify
61
61
  DummyLib::CALLBACKS << _v3
62
62
  _v4 = DummyLib.regress_test_callback_destroy_notify _v1, _v2, _v3
@@ -74,7 +74,7 @@ describe GirFFI::Builder::Function do
74
74
 
75
75
  expected = <<-CODE
76
76
  def self.new_from_file x
77
- _v1 = GirFFI::InPointer.from :utf8, x
77
+ _v1 = GirFFI::InPointer.from(:utf8, x)
78
78
  _v2 = FFI::MemoryPointer.new(:pointer).write_pointer nil
79
79
  _v3 = DummyLib.regress_test_obj_new_from_file _v1, _v2
80
80
  GirFFI::ArgHelper.check_error(_v2)
@@ -93,7 +93,7 @@ describe GirFFI::Builder::Function do
93
93
 
94
94
  expected = <<-CODE
95
95
  def self.gvalue_in value
96
- _v1 = ::GObject::Value.from value
96
+ _v1 = ::GObject::Value.from(value)
97
97
  DummyLib.gi_marshalling_tests_gvalue_in _v1
98
98
 
99
99
  end
@@ -109,7 +109,7 @@ describe GirFFI::Builder::Function do
109
109
 
110
110
  expected = <<-CODE
111
111
  def self.test_array_int_null_in arr
112
- _v1 = GirFFI::InPointer.from_array :gint32, arr
112
+ _v1 = GirFFI::InPointer.from([:c, :gint32], arr)
113
113
  len = arr.nil? ? 0 : arr.length
114
114
  _v2 = len
115
115
  DummyLib.regress_test_array_int_null_in _v1, _v2
@@ -64,6 +64,7 @@ describe GirFFI::Builder::Type::Struct do
64
64
 
65
65
  stub(type = Object.new).pointer? { false }
66
66
  stub(type).tag { :gint32 }
67
+ stub(type).flattened_tag { :gint32 }
67
68
 
68
69
  stub(@field).field_type { type }
69
70
  stub(@field).name { "bar" }
@@ -21,19 +21,6 @@ describe GirFFI::InfoExt::ITypeInfo do
21
21
  end
22
22
  end
23
23
 
24
- describe "#subtype_tag" do
25
- it "returns :gpointer if the param_type is a pointer with tag :void" do
26
- type_info = testclass.new
27
-
28
- stub(subtype0 = Object.new).tag { :void }
29
- stub(subtype0).pointer? { true }
30
-
31
- mock(type_info).param_type(0) { subtype0 }
32
-
33
- assert_equal :gpointer, type_info.subtype_tag(0)
34
- end
35
- end
36
-
37
24
  describe "#element_type" do
38
25
  it "returns the element type for lists" do
39
26
  type_info = testclass.new
@@ -67,5 +54,38 @@ describe GirFFI::InfoExt::ITypeInfo do
67
54
  result = type_info.element_type
68
55
  result.must_be_nil
69
56
  end
57
+
58
+ it "returns :gpointer if the element type is a pointer with tag :void" do
59
+ type_info = testclass.new
60
+
61
+ stub(elm_type = Object.new).tag { :void }
62
+ stub(elm_type).pointer? { true }
63
+
64
+ mock(type_info).tag {:glist}
65
+ mock(type_info).param_type(0) { elm_type }
66
+
67
+ assert_equal :gpointer, type_info.element_type
68
+ end
69
+ end
70
+
71
+ describe "#type_specification" do
72
+ describe "for a simple type" do
73
+ it "returns the type tag" do
74
+ type_info = testclass.new
75
+ mock(type_info).tag { :uint32 }
76
+ type_info.type_specification.must_equal ":uint32"
77
+ end
78
+ end
79
+
80
+ describe "for a zero-terminated array" do
81
+ it "returns the pair [:strv, element_type]" do
82
+ type_info = testclass.new
83
+ mock(type_info).tag { :array }
84
+ stub(type_info).element_type { :utf8 }
85
+ stub(type_info).zero_terminated? { true }
86
+ stub(type_info).array_type { :c }
87
+ type_info.type_specification.must_equal "[:strv, :utf8]"
88
+ end
89
+ end
70
90
  end
71
91
  end
@@ -490,20 +490,24 @@ describe "GIMarshallingTests" do
490
490
  assert_equal [-1, 0, 1, 2], res
491
491
  end
492
492
 
493
- it "has a working function #array_gvariant_(none)_in" do
494
- v1 = GLib::Variant.new_int32(27)
495
- v2 = GLib::Variant.new_string("Hello")
496
- if GIMarshallingTests._builder.setup_method :array_gvariant_in
497
- GIMarshallingTests.array_gvariant_in [v1, v2]
498
- else
499
- GIMarshallingTests.array_gvariant_none_in [v1, v2]
500
- end
501
-
502
- pass
503
- # TODO: Can we determine that result should be an array?
504
- # assert_equal 27, res[0].get_int32
505
- # assert_equal "Hello", res[1].get_string
506
- end
493
+ it "has a working function #array_gvariant_(none)_in"
494
+ # FIXME: Test was disabled since the implementation of the return value
495
+ # handling was never correct.
496
+ #
497
+ #do
498
+ #v1 = GLib::Variant.new_int32(27)
499
+ #v2 = GLib::Variant.new_string("Hello")
500
+ #if GIMarshallingTests._builder.setup_method :array_gvariant_in
501
+ #GIMarshallingTests.array_gvariant_in [v1, v2]
502
+ #else
503
+ #GIMarshallingTests.array_gvariant_none_in [v1, v2]
504
+ #end
505
+
506
+ #pass
507
+ ## TODO: Can we determine that result should be an array?
508
+ ## assert_equal 27, res[0].get_int32
509
+ ## assert_equal "Hello", res[1].get_string
510
+ #end
507
511
 
508
512
  it "has a working function #array_in" do
509
513
  GIMarshallingTests.array_in [-1, 0, 1, 2]
data/test/lib/Makefile.am CHANGED
@@ -19,7 +19,7 @@ libgimarshallingtests_la_LDFLAGS = -module -avoid-version
19
19
  # g-i doesn't ship these as shared libraries anymore; we build them here
20
20
  Regress-1.0.gir: libregress.la Makefile
21
21
  $(AM_V_GEN) g-ir-scanner --include=cairo-1.0 --include=Gio-2.0 \
22
- --namespace=Regress --nsversion=1.0 \
22
+ --namespace=Regress --nsversion=1.0 --pkg=cairo-gobject \
23
23
  --warn-all --warn-error \
24
24
  --library=libregress.la \
25
25
  --libtool="$(top_builddir)/libtool" \
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gir_ffi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-22 00:00:00.000000000 Z
12
+ date: 2012-11-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
@@ -150,6 +150,7 @@ files:
150
150
  - lib/gir_ffi/info_ext/i_type_info.rb
151
151
  - lib/gir_ffi/info_ext/i_field_info.rb
152
152
  - lib/gir_ffi/info_ext/i_property_info.rb
153
+ - lib/gir_ffi/info_ext/i_registered_type_info.rb
153
154
  - lib/gir_ffi/module_base.rb
154
155
  - lib/gir_ffi/class_base.rb
155
156
  - lib/gir_ffi/object_base.rb
@@ -169,6 +170,7 @@ files:
169
170
  - lib/ffi-glib/list.rb
170
171
  - lib/ffi-glib/hash_table.rb
171
172
  - lib/ffi-glib/list_methods.rb
173
+ - lib/ffi-glib/strv.rb
172
174
  - lib/ffi-glib/byte_array.rb
173
175
  - lib/ffi-glib/ptr_array.rb
174
176
  - lib/ffi-glib/s_list.rb