gir_ffi 0.1.0 → 0.2.0

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.
Files changed (78) hide show
  1. data/History.txt +14 -0
  2. data/TODO.rdoc +10 -5
  3. data/lib/ffi-glib.rb +7 -73
  4. data/lib/ffi-glib/array.rb +29 -4
  5. data/lib/ffi-glib/byte_array.rb +15 -1
  6. data/lib/ffi-glib/hash_table.rb +31 -24
  7. data/lib/ffi-glib/list.rb +28 -0
  8. data/lib/ffi-glib/list_methods.rb +10 -2
  9. data/lib/ffi-glib/ptr_array.rb +39 -0
  10. data/lib/ffi-glib/s_list.rb +29 -0
  11. data/lib/ffi-gobject.rb +49 -22
  12. data/lib/ffi-gobject/closure.rb +4 -3
  13. data/lib/ffi-gobject/helper.rb +20 -43
  14. data/lib/ffi-gobject/initially_unowned.rb +2 -0
  15. data/lib/ffi-gobject/object.rb +54 -0
  16. data/lib/ffi-gobject/ruby_closure.rb +22 -16
  17. data/lib/ffi-gobject/value.rb +54 -19
  18. data/lib/ffi-gobject_introspection/i_constant_info.rb +17 -1
  19. data/lib/ffi-gobject_introspection/i_field_info.rb +8 -0
  20. data/lib/ffi-gobject_introspection/i_property_info.rb +3 -1
  21. data/lib/ffi-gobject_introspection/lib.rb +19 -2
  22. data/lib/gir_ffi/arg_helper.rb +7 -45
  23. data/lib/gir_ffi/builder.rb +1 -1
  24. data/lib/gir_ffi/builder/argument.rb +148 -107
  25. data/lib/gir_ffi/builder/argument/base.rb +5 -5
  26. data/lib/gir_ffi/builder/argument/in_base.rb +2 -2
  27. data/lib/gir_ffi/builder/argument/in_out_base.rb +2 -3
  28. data/lib/gir_ffi/builder/argument/out_base.rb +2 -3
  29. data/lib/gir_ffi/builder/function.rb +11 -17
  30. data/lib/gir_ffi/builder/module.rb +26 -0
  31. data/lib/gir_ffi/builder/type.rb +5 -0
  32. data/lib/gir_ffi/builder/type/base.rb +2 -0
  33. data/lib/gir_ffi/builder/type/callback.rb +18 -3
  34. data/lib/gir_ffi/builder/type/constant.rb +4 -12
  35. data/lib/gir_ffi/builder/type/enum.rb +15 -6
  36. data/lib/gir_ffi/builder/type/interface.rb +4 -0
  37. data/lib/gir_ffi/builder/type/object.rb +11 -0
  38. data/lib/gir_ffi/builder/type/struct_based.rb +14 -4
  39. data/lib/gir_ffi/builder/type/union.rb +13 -7
  40. data/lib/gir_ffi/builder/type/with_layout.rb +59 -8
  41. data/lib/gir_ffi/class_base.rb +8 -1
  42. data/lib/gir_ffi/in_out_pointer.rb +17 -18
  43. data/lib/gir_ffi/in_pointer.rb +8 -1
  44. data/lib/gir_ffi/type_map.rb +12 -0
  45. data/lib/gir_ffi/variable_name_generator.rb +12 -0
  46. data/lib/gir_ffi/version.rb +1 -1
  47. data/test/ffi-glib/array_test.rb +54 -0
  48. data/test/ffi-glib/byte_array_test.rb +21 -0
  49. data/test/ffi-glib/glib_overrides_test.rb +1 -46
  50. data/test/ffi-glib/hash_table_test.rb +24 -0
  51. data/test/ffi-glib/list_test.rb +46 -0
  52. data/test/ffi-glib/ptr_array_test.rb +51 -0
  53. data/test/ffi-glib/s_list_test.rb +46 -0
  54. data/test/ffi-gobject/g_object_overrides_test.rb +8 -8
  55. data/test/ffi-gobject/gobject_test.rb +26 -0
  56. data/test/ffi-gobject/object_test.rb +12 -0
  57. data/test/ffi-gobject_introspection/i_constant_info_test.rb +5 -1
  58. data/test/ffi-gobject_introspection/lib_test.rb +56 -0
  59. data/test/integration/generated_gimarshallingtests_test.rb +118 -76
  60. data/test/integration/generated_regress_test.rb +220 -62
  61. data/test/integration/pretty_print_test.rb +11 -0
  62. data/test/type_builder_test.rb +0 -48
  63. data/test/unintrospectable_type_builder_test.rb +8 -2
  64. data/test/unit/builder_test.rb +1 -1
  65. data/test/unit/callback_builder_test.rb +19 -0
  66. data/test/unit/constant_builder_test.rb +11 -0
  67. data/test/unit/enum_builder_test.rb +25 -0
  68. data/test/unit/function_builder_test.rb +17 -0
  69. data/test/unit/in_out_pointer_test.rb +11 -0
  70. data/test/unit/in_pointer_test.rb +6 -2
  71. data/test/unit/interface_builder_test.rb +17 -0
  72. data/test/unit/module_builder_test.rb +95 -0
  73. data/test/unit/object_type_builder_test.rb +24 -0
  74. data/test/unit/struct_builder_test.rb +106 -0
  75. data/test/unit/union_builder_test.rb +17 -0
  76. data/test/unit/variable_name_generator_test.rb +16 -0
  77. metadata +102 -75
  78. data/test/module_builder_test.rb +0 -53
@@ -109,6 +109,7 @@ module GirFFI
109
109
  strv_to_utf8_array ptr.read_pointer
110
110
  end
111
111
 
112
+ # FIXME: Make GLib::Strv a class.
112
113
  def self.strv_to_utf8_array strv
113
114
  return [] if strv.null?
114
115
  arr, offset = [], 0
@@ -119,45 +120,6 @@ module GirFFI
119
120
  return arr
120
121
  end
121
122
 
122
- def self.utf8_array_to_glist arr
123
- return nil if arr.nil?
124
- arr.inject(GLib.list_new :utf8) { |lst, str|
125
- GLib.list_append lst, InPointer.from(:utf8, str) }
126
- end
127
-
128
- def self.gint32_array_to_glist arr
129
- return nil if arr.nil?
130
- arr.inject(GLib.list_new :gint32) { |lst, int|
131
- GLib.list_append lst, cast_int32_to_pointer(int) }
132
- end
133
-
134
- def self.utf8_array_to_gslist arr
135
- return nil if arr.nil?
136
- arr.reverse.inject(GLib.slist_new :utf8) { |lst, str|
137
- GLib.slist_prepend lst, InPointer.from(:utf8, str) }
138
- end
139
-
140
- def self.gint32_array_to_gslist arr
141
- return nil if arr.nil?
142
- arr.reverse.inject(GLib.slist_new :gint32) { |lst, int|
143
- GLib.slist_prepend lst, cast_int32_to_pointer(int) }
144
- end
145
-
146
- def self.hash_to_ghash keytype, valtype, hash
147
- return nil if hash.nil?
148
- ghash = GLib.hash_table_new keytype, valtype
149
- hash.each do |key, val|
150
- ghash.insert key, val
151
- end
152
- ghash
153
- end
154
-
155
- def self.void_array_to_gslist ary
156
- return nil if ary.nil?
157
- return ary if ary.is_a? GLib::SList
158
- raise NotImplementedError
159
- end
160
-
161
123
  def self.check_error errpp
162
124
  errp = errpp.read_pointer
163
125
  # FIXME: Do not depend on GError from GObjectIntrospection namespace.
@@ -176,9 +138,13 @@ module GirFFI
176
138
 
177
139
  # FIXME: Quasi-circular dependency on generated module
178
140
  def self.object_pointer_to_object optr
141
+ gtype = GObject.type_from_instance_pointer optr
142
+ wrap_object_pointer_by_gtype optr, gtype
143
+ end
144
+
145
+ def self.wrap_object_pointer_by_gtype optr, gtype
179
146
  return nil if optr.null?
180
- gtype = ::GObject.type_from_instance_pointer optr
181
- klass = GirFFI::Builder.build_by_gtype gtype
147
+ klass = Builder.build_by_gtype gtype
182
148
  klass.wrap optr
183
149
  end
184
150
 
@@ -204,9 +170,5 @@ module GirFFI
204
170
  def self.cast_pointer_to_int32 ptr
205
171
  cast_uint32_to_int32(ptr.address & 0xffffffff)
206
172
  end
207
-
208
- def self.cast_int32_to_pointer int
209
- FFI::Pointer.new(int)
210
- end
211
173
  end
212
174
  end
@@ -34,6 +34,7 @@ module GirFFI
34
34
  # TODO: Move elsewhere, perhaps to Builder::Function.
35
35
  def self.attach_ffi_function lib, info
36
36
  sym = info.symbol
37
+ return if lib.method_defined? sym
37
38
  argtypes = ffi_function_argument_types info
38
39
  rt = ffi_function_return_type info
39
40
 
@@ -60,7 +61,6 @@ module GirFFI
60
61
 
61
62
  def self.ffi_function_return_type info
62
63
  rt = info.return_type
63
- return :string if rt.tag == :utf8
64
64
  itypeinfo_to_ffitype rt
65
65
  end
66
66
 
@@ -10,43 +10,49 @@ require 'gir_ffi/builder/argument/hash_table_base'
10
10
 
11
11
  module GirFFI::Builder
12
12
  module Argument
13
- def self.build function_builder, arginfo, libmodule
13
+ def self.build var_gen, arginfo, libmodule
14
14
  {
15
15
  :inout => InOutArgument,
16
16
  :in => InArgument,
17
17
  :out => OutArgument
18
- }[arginfo.direction].build function_builder, arginfo, libmodule
18
+ }[arginfo.direction].build var_gen, arginfo, libmodule
19
19
  end
20
20
  end
21
21
 
22
22
  module InArgument
23
- def self.build function_builder, arginfo, libmodule
23
+ def self.build var_gen, arginfo, libmodule
24
24
  type = arginfo.argument_type
25
- klass = case type.tag
26
- when :interface
27
- if type.interface.info_type == :callback
28
- CallbackInArgument
29
- else
30
- RegularInArgument
31
- end
32
- when :void
33
- VoidInArgument
34
- when :array
35
- if type.array_type == :c
36
- CArrayInArgument
37
- else
38
- RegularInArgument
39
- end
40
- when :glist, :gslist
41
- ListInArgument
42
- when :ghash
43
- HashTableInArgument
44
- when :utf8
45
- Utf8InArgument
46
- else
47
- RegularInArgument
48
- end
49
- klass.new function_builder, arginfo, libmodule
25
+ klass = builder_for type
26
+ klass.new var_gen, arginfo.name, type, libmodule
27
+ end
28
+
29
+ def self.builder_for type
30
+ case type.tag
31
+ when :interface
32
+ if type.interface.info_type == :callback
33
+ CallbackInArgument
34
+ else
35
+ RegularInArgument
36
+ end
37
+ when :void
38
+ VoidInArgument
39
+ when :array
40
+ if type.array_type == :c
41
+ CArrayInArgument
42
+ else
43
+ RegularInArgument
44
+ end
45
+ when :glist
46
+ ListInArgument
47
+ when :gslist
48
+ SListInArgument
49
+ when :ghash
50
+ HashTableInArgument
51
+ when :utf8
52
+ Utf8InArgument
53
+ else
54
+ RegularInArgument
55
+ end
50
56
  end
51
57
  end
52
58
 
@@ -81,18 +87,25 @@ module GirFFI::Builder
81
87
  end
82
88
  end
83
89
 
84
- # Implements argument processing for glist and gslist arguments with
90
+ # Implements argument processing for glist arguments with
85
91
  # direction :in.
86
92
  class ListInArgument < Argument::InBase
87
93
  def pre
88
- [ "#{callarg} = GirFFI::ArgHelper.#{subtype_tag}_array_to_#{type_tag} #{@name}" ]
94
+ [ "#{callarg} = GLib::List.from_array #{subtype_tag.inspect}, #{@name}" ]
95
+ end
96
+ end
97
+
98
+ # Implements argument processing for gslist arguments with direction :in.
99
+ class SListInArgument < Argument::InBase
100
+ def pre
101
+ [ "#{callarg} = GLib::SList.from_array #{subtype_tag.inspect}, #{@name}" ]
89
102
  end
90
103
  end
91
104
 
92
105
  # Implements argument processing for ghash arguments with direction :in.
93
106
  class HashTableInArgument < Argument::InBase
94
107
  def pre
95
- [ "#{callarg} = GirFFI::ArgHelper.hash_to_ghash #{subtype_tag(0).inspect}, #{subtype_tag(1).inspect}, #{@name}" ]
108
+ [ "#{callarg} = GLib::HashTable.from_hash #{subtype_tag(0).inspect}, #{subtype_tag(1).inspect}, #{@name}" ]
96
109
  end
97
110
  end
98
111
 
@@ -121,7 +134,7 @@ module GirFFI::Builder
121
134
 
122
135
  # Implements argument processing for arguments with direction :out.
123
136
  module OutArgument
124
- def self.build function_builder, arginfo, libmodule
137
+ def self.build var_gen, arginfo, libmodule
125
138
  type = arginfo.argument_type
126
139
  klass = case type.tag
127
140
  when :interface
@@ -129,7 +142,11 @@ module GirFFI::Builder
129
142
  when :enum, :flags
130
143
  EnumOutArgument
131
144
  else
132
- InterfaceOutArgument
145
+ if arginfo.caller_allocates?
146
+ AllocatedInterfaceOutArgument
147
+ else
148
+ InterfaceOutArgument
149
+ end
133
150
  end
134
151
  when :array
135
152
  if type.zero_terminated?
@@ -151,7 +168,7 @@ module GirFFI::Builder
151
168
  else
152
169
  RegularOutArgument
153
170
  end
154
- klass.new function_builder, arginfo, libmodule
171
+ klass.new var_gen, arginfo.name, type, libmodule
155
172
  end
156
173
  end
157
174
 
@@ -183,23 +200,27 @@ module GirFFI::Builder
183
200
  end
184
201
  end
185
202
 
203
+ # Implements argument processing for interface arguments with direction
204
+ # :out (structs, objects, etc.), allocated by the caller.
205
+ class AllocatedInterfaceOutArgument < Argument::OutBase
206
+ def pre
207
+ [ "#{callarg} = #{argument_class_name}.allocate" ]
208
+ end
209
+
210
+ def post
211
+ [ "#{retname} = #{callarg}" ]
212
+ end
213
+ end
214
+
186
215
  # Implements argument processing for interface arguments with direction
187
216
  # :out (structs, objects, etc.).
188
217
  class InterfaceOutArgument < Argument::OutBase
189
218
  def pre
190
- if @arginfo.caller_allocates?
191
- [ "#{callarg} = #{argument_class_name}.allocate" ]
192
- else
193
- [ "#{callarg} = GirFFI::InOutPointer.for :pointer" ]
194
- end
219
+ [ "#{callarg} = GirFFI::InOutPointer.for :pointer" ]
195
220
  end
196
221
 
197
222
  def post
198
- if @arginfo.caller_allocates?
199
- [ "#{retname} = #{callarg}" ]
200
- else
201
- [ "#{retname} = #{argument_class_name}.wrap #{callarg}.to_value" ]
202
- end
223
+ [ "#{retname} = #{argument_class_name}.wrap #{callarg}.to_value" ]
203
224
  end
204
225
  end
205
226
 
@@ -282,7 +303,7 @@ module GirFFI::Builder
282
303
 
283
304
  # Implements argument processing for arguments with direction :inout.
284
305
  module InOutArgument
285
- def self.build function_builder, arginfo, libmodule
306
+ def self.build var_gen, arginfo, libmodule
286
307
  type = arginfo.argument_type
287
308
  klass = case type.tag
288
309
  when :interface
@@ -313,7 +334,7 @@ module GirFFI::Builder
313
334
  RegularInOutArgument
314
335
  end
315
336
 
316
- klass.new function_builder, arginfo, libmodule
337
+ klass.new var_gen, arginfo.name, type, libmodule
317
338
  end
318
339
  end
319
340
 
@@ -394,7 +415,7 @@ module GirFFI::Builder
394
415
  include Argument::ListBase
395
416
 
396
417
  def pre
397
- [ "#{callarg} = GirFFI::InOutPointer.from :pointer, GirFFI::ArgHelper.#{subtype_tag}_array_to_#{type_tag}(#{@name})" ]
418
+ [ "#{callarg} = GirFFI::InOutPointer.from :pointer, GLib::List.from_array(#{subtype_tag.inspect}, #{@name})" ]
398
419
  end
399
420
 
400
421
  def post
@@ -404,12 +425,11 @@ module GirFFI::Builder
404
425
 
405
426
  # Implements argument processing for gslist arguments with direction
406
427
  # :inout.
407
- # FIXME: Merge code with ListInOutArgument somehow.
408
428
  class SListInOutArgument < Argument::InOutBase
409
429
  include Argument::ListBase
410
430
 
411
431
  def pre
412
- [ "#{callarg} = GirFFI::InOutPointer.from :pointer, GirFFI::ArgHelper.#{subtype_tag}_array_to_#{type_tag}(#{@name})" ]
432
+ [ "#{callarg} = GirFFI::InOutPointer.from :pointer, GLib::SList.from_array(#{subtype_tag.inspect}, #{@name})" ]
413
433
  end
414
434
 
415
435
  def post
@@ -423,7 +443,7 @@ module GirFFI::Builder
423
443
  include Argument::HashTableBase
424
444
 
425
445
  def pre
426
- [ "#{callarg} = GirFFI::InOutPointer.from :pointer, GirFFI::ArgHelper.hash_to_ghash(#{key_t}, #{val_t}, #{@name})" ]
446
+ [ "#{callarg} = GirFFI::InOutPointer.from :pointer, GLib::HashTable.from_hash(#{key_t}, #{val_t}, #{@name})" ]
427
447
  end
428
448
 
429
449
  def post
@@ -451,58 +471,73 @@ module GirFFI::Builder
451
471
  # Implements argument processing for return values.
452
472
  class ReturnValue < Argument::Base
453
473
  def cvar
454
- @cvar ||= @function_builder.new_var
474
+ @cvar ||= @var_gen.new_var
455
475
  end
456
476
 
457
477
  def retname
458
- @retname ||= @function_builder.new_var
478
+ @retname ||= @var_gen.new_var
459
479
  end
460
480
 
461
- def type_info
462
- @arginfo.return_type
481
+ def self.build var_gen, arginfo
482
+ type = arginfo.return_type
483
+ klass = builder_for(type, arginfo.constructor?)
484
+ klass.new var_gen, arginfo.name, type, nil
463
485
  end
464
486
 
465
- def self.build function_builder, arginfo
466
- type = arginfo.return_type
467
- klass = case type.tag
468
- when :void
469
- VoidReturnValue
470
- when :interface
471
- case type.interface.info_type
472
- when :struct, :union
473
- InterfaceReturnValue
474
- when :interface, :object
475
- if arginfo.constructor?
476
- ConstructorReturnValue
477
- else
478
- ObjectReturnValue
479
- end
480
- else
481
- RegularReturnValue
482
- end
483
- when :array
484
- if type.zero_terminated?
485
- StrvReturnValue
486
- else
487
- case type.array_type
488
- when :c
489
- CArrayReturnValue
490
- when :array
491
- ArrayReturnValue
492
- when :byte_array
493
- ByteArrayReturnValue
494
- end
495
- end
496
- when :glist
497
- ListReturnValue
498
- when :gslist
499
- SListReturnValue
500
- when :ghash
501
- HashTableReturnValue
502
- else
503
- RegularReturnValue
504
- end
505
- klass.new function_builder, arginfo, nil
487
+ def self.builder_for type, is_constructor
488
+ if type.tag == :interface and
489
+ [:interface, :object].include? type.interface.info_type
490
+ if is_constructor
491
+ ConstructorReturnValue
492
+ else
493
+ ObjectReturnValue
494
+ end
495
+ else
496
+ builder_for_field_getter type
497
+ end
498
+ end
499
+
500
+ def self.builder_for_field_getter type
501
+ case type.tag
502
+ when :void
503
+ if type.pointer?
504
+ RegularReturnValue
505
+ else
506
+ VoidReturnValue
507
+ end
508
+ when :interface
509
+ case type.interface.info_type
510
+ when :struct, :union, :interface, :object
511
+ InterfaceReturnValue
512
+ else
513
+ RegularReturnValue
514
+ end
515
+ when :array
516
+ if type.zero_terminated?
517
+ StrvReturnValue
518
+ else
519
+ case type.array_type
520
+ when :c
521
+ CArrayReturnValue
522
+ when :array
523
+ ArrayReturnValue
524
+ when :byte_array
525
+ ByteArrayReturnValue
526
+ else
527
+ PtrArrayReturnValue
528
+ end
529
+ end
530
+ when :glist
531
+ ListReturnValue
532
+ when :gslist
533
+ SListReturnValue
534
+ when :ghash
535
+ HashTableReturnValue
536
+ when :utf8
537
+ Utf8ReturnValue
538
+ else
539
+ RegularReturnValue
540
+ end
506
541
  end
507
542
 
508
543
  def inarg
@@ -555,6 +590,13 @@ module GirFFI::Builder
555
590
  end
556
591
  end
557
592
 
593
+ # Implements argument processing for UTF8 string return values.
594
+ class Utf8ReturnValue < ReturnValue
595
+ def post
596
+ [ "#{retname} = GirFFI::ArgHelper.ptr_to_utf8 #{@cvar}" ]
597
+ end
598
+ end
599
+
558
600
  # Implements argument processing for GList return values.
559
601
  class ListReturnValue < ReturnValue
560
602
  include Argument::ListBase
@@ -582,14 +624,14 @@ module GirFFI::Builder
582
624
  end
583
625
  end
584
626
 
585
- # Implements argument processing for GHashTable return values.
627
+ # Implements argument processing for GByteArray return values.
586
628
  class ByteArrayReturnValue < ReturnValue
587
629
  def post
588
630
  [ "#{retname} = GLib::ByteArray.wrap(#{cvar})" ]
589
631
  end
590
632
  end
591
633
 
592
- # Implements argument processing for GHashTable return values.
634
+ # Implements argument processing for GArray return values.
593
635
  class ArrayReturnValue < ReturnValue
594
636
  include Argument::ListBase
595
637
 
@@ -599,18 +641,17 @@ module GirFFI::Builder
599
641
  end
600
642
  end
601
643
 
644
+ # Implements argument processing for GPtrArray return values.
645
+ class PtrArrayReturnValue < ReturnValue
646
+ def post
647
+ [ "#{retname} = GLib::PtrArray.wrap(#{cvar})" ]
648
+ end
649
+ end
650
+
602
651
  # Implements argument processing for other return values.
603
652
  class RegularReturnValue < ReturnValue
604
653
  def retval
605
- if RUBY_VERSION < "1.9"
606
- @cvar
607
- else
608
- if type_tag == :utf8
609
- "#{cvar}.force_encoding('utf-8')"
610
- else
611
- @cvar
612
- end
613
- end
654
+ @cvar
614
655
  end
615
656
  end
616
657
 
@@ -619,7 +660,7 @@ module GirFFI::Builder
619
660
  # presence is indicated by the 'throws' attribute of the function.
620
661
  class ErrorArgument < Argument::Base
621
662
  def callarg
622
- @callarg ||= @function_builder.new_var
663
+ @callarg ||= @var_gen.new_var
623
664
  end
624
665
 
625
666
  def pre