gir_ffi 0.0.8 → 0.0.9

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 (46) hide show
  1. data/History.txt +11 -0
  2. data/TODO.rdoc +5 -0
  3. data/examples/01_empty_window.rb +0 -1
  4. data/examples/02_hello_world.rb +0 -1
  5. data/examples/03_upgraded_hello_world.rb +0 -1
  6. data/examples/04_webkit.rb +0 -1
  7. data/lib/gir_ffi/arg_helper.rb +231 -94
  8. data/lib/gir_ffi/builder/argument.rb +372 -46
  9. data/lib/gir_ffi/builder/module.rb +25 -10
  10. data/lib/gir_ffi/builder/type/constant.rb +39 -0
  11. data/lib/gir_ffi/builder/type/enum.rb +15 -5
  12. data/lib/gir_ffi/builder/type/registered_type.rb +25 -6
  13. data/lib/gir_ffi/builder/type/struct.rb +1 -9
  14. data/lib/gir_ffi/builder/type/union.rb +5 -0
  15. data/lib/gir_ffi/builder/type.rb +13 -14
  16. data/lib/gir_ffi/builder.rb +7 -4
  17. data/lib/gir_ffi/builder_helper.rb +4 -3
  18. data/lib/gir_ffi/i_base_info.rb +4 -0
  19. data/lib/gir_ffi/i_constant_info.rb +9 -0
  20. data/lib/gir_ffi/i_registered_type_info.rb +0 -1
  21. data/lib/gir_ffi/i_repository.rb +8 -2
  22. data/lib/gir_ffi/i_type_info.rb +7 -0
  23. data/lib/gir_ffi/lib.rb +41 -3
  24. data/lib/gir_ffi/overrides/glib.rb +188 -4
  25. data/lib/gir_ffi/overrides/gobject.rb +16 -5
  26. data/tasks/test.rake +1 -1
  27. data/test/arg_helper_test.rb +5 -5
  28. data/test/builder_test.rb +64 -41
  29. data/test/class_base_test.rb +1 -1
  30. data/test/function_definition_builder_test.rb +24 -2
  31. data/test/g_object_overrides_test.rb +1 -3
  32. data/test/g_object_test.rb +1 -1
  33. data/test/generated_gimarshallingtests_test.rb +1677 -0
  34. data/test/generated_gio_test.rb +1 -1
  35. data/test/generated_gtk_test.rb +31 -2
  36. data/test/generated_regress_test.rb +278 -54
  37. data/test/girffi_test.rb +20 -5
  38. data/test/glib_overrides_test.rb +81 -0
  39. data/test/gtk_overrides_test.rb +2 -3
  40. data/test/i_object_info_test.rb +1 -1
  41. data/test/i_repository_test.rb +3 -4
  42. data/test/lib/Makefile.am +18 -2
  43. data/test/module_builder_test.rb +1 -1
  44. data/test/test_helper.rb +88 -5
  45. data/test/type_builder_test.rb +7 -10
  46. metadata +16 -13
@@ -46,23 +46,19 @@ module GirFFI::Builder
46
46
  end
47
47
 
48
48
  def type_tag
49
- type_info.tag
49
+ tag = type_info.tag
50
+ tag == :GType ? :gtype : tag
50
51
  end
51
52
 
52
- def subtype_tag
53
- st = type_info.param_type(0)
53
+ def subtype_tag index=0
54
+ st = type_info.param_type(index)
54
55
  t = st.tag
55
56
  case t
56
57
  when :GType
57
58
  return :gtype
58
59
  when :interface
59
- raise NotImplementedError if st.pointer?
60
- iface = st.interface
61
- if iface.name == 'Value' and iface.namespace == 'GObject'
62
- return :gvalue
63
- else
64
- raise NotImplementedError
65
- end
60
+ return :interface_pointer if st.pointer?
61
+ return :interface
66
62
  else
67
63
  return t
68
64
  end
@@ -70,7 +66,12 @@ module GirFFI::Builder
70
66
 
71
67
  def argument_class_name
72
68
  iface = type_info.interface
73
- "::#{iface.namespace}::#{iface.name}"
69
+ "::#{iface.safe_namespace}::#{iface.name}"
70
+ end
71
+
72
+ def subtype_class_name index=0
73
+ iface = type_info.param_type(index).interface
74
+ "::#{iface.safe_namespace}::#{iface.name}"
74
75
  end
75
76
 
76
77
  def array_size
@@ -130,9 +131,15 @@ module GirFFI::Builder
130
131
  when :void
131
132
  VoidInArgument
132
133
  when :array
133
- ArrayInArgument
134
+ if type.array_type == :c
135
+ CArrayInArgument
136
+ else
137
+ RegularInArgument
138
+ end
134
139
  when :glist, :gslist
135
140
  ListInArgument
141
+ when :ghash
142
+ HashTableInArgument
136
143
  when :utf8
137
144
  Utf8InArgument
138
145
  else
@@ -161,7 +168,7 @@ module GirFFI::Builder
161
168
  end
162
169
 
163
170
  # Implements argument processing for array arguments with direction :in.
164
- class ArrayInArgument < InArgument
171
+ class CArrayInArgument < InArgument
165
172
  def post
166
173
  unless @arginfo.ownership_transfer == :everything
167
174
  if subtype_tag == :utf8
@@ -183,13 +190,21 @@ module GirFFI::Builder
183
190
  end
184
191
  end
185
192
 
186
- # Implements argument processing for gslist arguments with direction :in.
193
+ # Implements argument processing for glist and gslist arguments with
194
+ # direction :in.
187
195
  class ListInArgument < InArgument
188
196
  def pre
189
197
  [ "#{@callarg} = GirFFI::ArgHelper.#{subtype_tag}_array_to_#{type_tag} #{@name}" ]
190
198
  end
191
199
  end
192
200
 
201
+ # Implements argument processing for ghash arguments with direction :in.
202
+ class HashTableInArgument < InArgument
203
+ def pre
204
+ [ "#{@callarg} = GirFFI::ArgHelper.hash_to_ghash #{subtype_tag(0).inspect}, #{subtype_tag(1).inspect}, #{@name}" ]
205
+ end
206
+ end
207
+
193
208
  # Implements argument processing for UTF8 string arguments with direction
194
209
  # :in.
195
210
  class Utf8InArgument < InArgument
@@ -228,13 +243,32 @@ module GirFFI::Builder
228
243
  end
229
244
 
230
245
  def self.build function_builder, arginfo, libmodule
246
+ type = arginfo.argument_type
231
247
  klass = case arginfo.argument_type.tag
232
248
  when :interface
233
- InterfaceOutArgument
249
+ case type.interface.info_type
250
+ when :enum, :flags
251
+ EnumOutArgument
252
+ else
253
+ InterfaceOutArgument
254
+ end
234
255
  when :array
235
- ArrayOutArgument
256
+ if type.zero_terminated?
257
+ StrvOutArgument
258
+ else
259
+ case type.array_type
260
+ when :c
261
+ CArrayOutArgument
262
+ when :array
263
+ ArrayOutArgument
264
+ end
265
+ end
266
+ when :glist
267
+ ListOutArgument
236
268
  when :gslist
237
- GSListOutArgument
269
+ SListOutArgument
270
+ when :ghash
271
+ HashTableOutArgument
238
272
  else
239
273
  RegularOutArgument
240
274
  end
@@ -242,6 +276,22 @@ module GirFFI::Builder
242
276
  end
243
277
  end
244
278
 
279
+ # Implements argument processing for arguments with direction
280
+ # :out that are enums
281
+ class EnumOutArgument < OutArgument
282
+ def post
283
+ pst = [ "#{@retname} = #{argument_class_name}[GirFFI::ArgHelper.outptr_to_gint32 #{@callarg}]" ]
284
+ if @arginfo.ownership_transfer == :everything
285
+ pst << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
286
+ end
287
+ pst
288
+ end
289
+
290
+ def pre
291
+ [ "#{@callarg} = GirFFI::ArgHelper.gint32_outptr" ]
292
+ end
293
+ end
294
+
245
295
  # Implements argument processing for interface arguments with direction
246
296
  # :out (structs, objects, etc.).
247
297
  class InterfaceOutArgument < OutArgument
@@ -264,7 +314,7 @@ module GirFFI::Builder
264
314
 
265
315
  # Implements argument processing for array arguments with direction
266
316
  # :out.
267
- class ArrayOutArgument < OutArgument
317
+ class CArrayOutArgument < OutArgument
268
318
  def pre
269
319
  [ "#{@callarg} = GirFFI::ArgHelper.pointer_outptr" ]
270
320
  end
@@ -273,11 +323,20 @@ module GirFFI::Builder
273
323
  size = array_size
274
324
  tag = subtype_tag
275
325
 
276
- pp = [ "#{@retname} = GirFFI::ArgHelper.outptr_to_#{tag}_array #{@callarg}, #{size}" ]
326
+ pp = []
327
+
328
+ if tag == :interface or tag == :interface_pointer
329
+ pp << "#{@retname} = GirFFI::ArgHelper.outptr_to_#{tag}_array #{subtype_class_name}, #{@callarg}, #{size}"
330
+ else
331
+ pp << "#{@retname} = GirFFI::ArgHelper.outptr_to_#{tag}_array #{@callarg}, #{size}"
332
+ end
277
333
 
278
334
  if @arginfo.ownership_transfer == :everything
279
- if tag == :utf8
335
+ case tag
336
+ when :utf8
280
337
  pp << "GirFFI::ArgHelper.cleanup_ptr_array_ptr #{@callarg}, #{size}"
338
+ when :interface
339
+ pp << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
281
340
  else
282
341
  pp << "GirFFI::ArgHelper.cleanup_ptr_ptr #{@callarg}"
283
342
  end
@@ -287,17 +346,82 @@ module GirFFI::Builder
287
346
  end
288
347
  end
289
348
 
349
+ # Implements argument processing for strv arguments with direction
350
+ # :out.
351
+ class StrvOutArgument < OutArgument
352
+ def pre
353
+ [ "#{@callarg} = GirFFI::ArgHelper.pointer_outptr" ]
354
+ end
355
+
356
+ def postpost
357
+ [ "#{@retname} = GirFFI::ArgHelper.outptr_strv_to_utf8_array #{@callarg}" ]
358
+ end
359
+ end
360
+
361
+ # Implements argument processing for GArray arguments with direction
362
+ # :out.
363
+ class ArrayOutArgument < OutArgument
364
+ def pre
365
+ [ "#{@callarg} = GirFFI::ArgHelper.pointer_outptr" ]
366
+ end
367
+
368
+ def post
369
+ tag = subtype_tag
370
+ etype = GirFFI::Builder::TAG_TYPE_MAP[tag] || tag
371
+
372
+ pp = []
373
+
374
+ pp << "#{@retname} = GLib::Array.wrap(GirFFI::ArgHelper.outptr_to_pointer #{@callarg})"
375
+ pp << "#{@retname}.element_type = #{etype.inspect}"
376
+
377
+ if @arginfo.ownership_transfer == :everything
378
+ pp << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
379
+ end
380
+
381
+ pp
382
+ end
383
+ end
384
+
385
+ # Implements argument processing for glist arguments with direction
386
+ # :out.
387
+ class ListOutArgument < OutArgument
388
+ def pre
389
+ [ "#{@callarg} = GirFFI::ArgHelper.pointer_outptr" ]
390
+ end
391
+
392
+ def post
393
+ elm_t = subtype_tag.inspect
394
+ [ "#{@retname} = GLib::List.wrap #{elm_t}, GirFFI::ArgHelper.outptr_to_pointer(#{@callarg})" ]
395
+ end
396
+ end
397
+
290
398
  # Implements argument processing for gslist arguments with direction
291
399
  # :out.
292
- class GSListOutArgument < OutArgument
400
+ class SListOutArgument < OutArgument
401
+ def pre
402
+ [ "#{@callarg} = GirFFI::ArgHelper.pointer_outptr" ]
403
+ end
404
+
405
+ def post
406
+ elm_t = subtype_tag.inspect
407
+ [ "#{@retname} = GLib::SList.wrap #{elm_t}, GirFFI::ArgHelper.outptr_to_pointer(#{@callarg})" ]
408
+ end
409
+ end
410
+
411
+ # Implements argument processing for ghash arguments with direction
412
+ # :out.
413
+ class HashTableOutArgument < OutArgument
293
414
  def pre
294
415
  [ "#{@callarg} = GirFFI::ArgHelper.pointer_outptr" ]
295
416
  end
296
417
 
297
418
  def postpost
298
- [ "#{@retname} = GirFFI::ArgHelper.outgslist_to_#{subtype_tag}_array #{@callarg}" ]
419
+ key_t = subtype_tag(0).inspect
420
+ val_t = subtype_tag(1).inspect
421
+ [ "#{@retname} = GLib::HashTable.wrap #{key_t}, #{val_t}, GirFFI::ArgHelper.outptr_to_pointer(#{@callarg})" ]
299
422
  end
300
423
  end
424
+
301
425
  # Implements argument processing for arguments with direction
302
426
  # :out that are neither arrays nor 'interfaces'.
303
427
  class RegularOutArgument < OutArgument
@@ -324,13 +448,32 @@ module GirFFI::Builder
324
448
  end
325
449
 
326
450
  def self.build function_builder, arginfo, libmodule
327
- raise NotImplementedError unless arginfo.ownership_transfer == :everything
328
-
329
- klass = case arginfo.argument_type.tag
451
+ type = arginfo.argument_type
452
+ klass = case type.tag
330
453
  when :interface
331
- raise NotImplementedError
454
+ case type.interface.info_type
455
+ when :enum, :flags
456
+ EnumInOutArgument
457
+ else
458
+ InterfaceInOutArgument
459
+ end
332
460
  when :array
333
- ArrayInOutArgument
461
+ if type.zero_terminated?
462
+ StrvInOutArgument
463
+ else
464
+ case type.array_type
465
+ when :c
466
+ CArrayInOutArgument
467
+ when :array
468
+ ArrayInOutArgument
469
+ end
470
+ end
471
+ when :glist
472
+ ListInOutArgument
473
+ when :gslist
474
+ SListInOutArgument
475
+ when :ghash
476
+ HashTableInOutArgument
334
477
  else
335
478
  RegularInOutArgument
336
479
  end
@@ -339,34 +482,147 @@ module GirFFI::Builder
339
482
  end
340
483
  end
341
484
 
342
- # Implements argument processing for array arguments with direction
485
+ # Implements argument processing for arguments with direction
486
+ # :inout that are enums.
487
+ class EnumInOutArgument < InOutArgument
488
+ def pre
489
+ pr = []
490
+ pr << "#{@callarg} = GirFFI::ArgHelper.gint32_to_inoutptr #{argument_class_name}[#{@name}]"
491
+ pr
492
+ end
493
+
494
+ def post
495
+ [ "#{@retname} = #{argument_class_name}[GirFFI::ArgHelper.outptr_to_gint32 #{@callarg}]",
496
+ "GirFFI::ArgHelper.cleanup_ptr #{@callarg}" ]
497
+ end
498
+ end
499
+
500
+ # Implements argument processing for interface arguments with direction
501
+ # :inout (structs, objects, etc.).
502
+ class InterfaceInOutArgument < InOutArgument
503
+ def pre
504
+ [ "#{@callarg} = GirFFI::ArgHelper.pointer_to_inoutptr #{@name}.to_ptr" ]
505
+ end
506
+
507
+ def post
508
+ [ "#{@retname} = #{argument_class_name}.wrap(GirFFI::ArgHelper.outptr_to_pointer #{@callarg})",
509
+ "GirFFI::ArgHelper.cleanup_ptr #{@callarg}" ]
510
+ end
511
+ end
512
+
513
+ # Implements argument processing for strv arguments with direction
343
514
  # :inout.
344
- class ArrayInOutArgument < InOutArgument
515
+ class StrvInOutArgument < InOutArgument
345
516
  def pre
346
517
  [ "#{@callarg} = GirFFI::ArgHelper.#{subtype_tag}_array_to_inoutptr #{@name}" ]
347
518
  end
348
519
 
349
520
  def post
521
+ [ "#{@retname} = GirFFI::ArgHelper.outptr_strv_to_utf8_array #{@callarg}" ]
522
+ end
523
+ end
524
+
525
+ # Implements argument processing for array arguments with direction
526
+ # :inout.
527
+ class CArrayInOutArgument < InOutArgument
528
+ def pre
529
+ [ "#{@callarg} = GirFFI::ArgHelper.#{subtype_tag}_array_to_inoutptr #{@name}" ]
530
+ end
531
+
532
+ def postpost
350
533
  tag = subtype_tag
351
- size = @length_arg.retname
534
+ size = array_size
352
535
  pst = [ "#{@retname} = GirFFI::ArgHelper.outptr_to_#{tag}_array #{@callarg}, #{size}" ]
353
- if tag == :utf8
354
- pst << "GirFFI::ArgHelper.cleanup_ptr_array_ptr #{@callarg}, #{size}"
536
+ if @arginfo.ownership_transfer == :nothing
537
+ pst << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
355
538
  else
356
- pst << "GirFFI::ArgHelper.cleanup_ptr_ptr #{@callarg}"
539
+ if tag == :utf8
540
+ pst << "GirFFI::ArgHelper.cleanup_ptr_array_ptr #{@callarg}, #{size}"
541
+ else
542
+ pst << "GirFFI::ArgHelper.cleanup_ptr_ptr #{@callarg}"
543
+ end
357
544
  end
358
545
  pst
359
546
  end
360
547
  end
361
548
 
362
- # Implements argument processing for arguments with direction
363
- # :inout that are neither arrays nor 'interfaces'.
364
- class RegularInOutArgument < InOutArgument
549
+ # Implements argument processing for GArray arguments with direction
550
+ # :out.
551
+ class ArrayInOutArgument < InOutArgument
552
+ def pre
553
+ [ "#{@callarg} = GirFFI::ArgHelper.pointer_to_inoutptr #{@name}" ]
554
+ end
555
+
365
556
  def post
366
- [ "#{@retname} = GirFFI::ArgHelper.outptr_to_#{type_tag} #{@callarg}",
367
- "GirFFI::ArgHelper.cleanup_ptr #{@callarg}" ]
557
+ tag = subtype_tag
558
+ etype = GirFFI::Builder::TAG_TYPE_MAP[tag] || tag
559
+
560
+ pp = []
561
+
562
+ pp << "#{@retname} = GLib::Array.wrap(GirFFI::ArgHelper.outptr_to_pointer #{@callarg})"
563
+ pp << "#{@retname}.element_type = #{etype.inspect}"
564
+ pp << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
565
+
566
+ pp
368
567
  end
568
+ end
369
569
 
570
+ # Implements argument processing for glist arguments with direction
571
+ # :inout.
572
+ class ListInOutArgument < InOutArgument
573
+ def pre
574
+ [ "#{@callarg} = GirFFI::ArgHelper.pointer_to_inoutptr(GirFFI::ArgHelper.#{subtype_tag}_array_to_#{type_tag} #{@name})" ]
575
+ end
576
+
577
+ def post
578
+ elm_t = subtype_tag.inspect
579
+ pp = []
580
+ pp << "#{@retname} = GLib::List.wrap #{elm_t}, GirFFI::ArgHelper.outptr_to_pointer(#{@callarg})"
581
+ pp << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
582
+ pp
583
+ end
584
+ end
585
+
586
+ # Implements argument processing for gslist arguments with direction
587
+ # :inout.
588
+ # FIXME: Merge code with ListInOutArgument somehow.
589
+ class SListInOutArgument < InOutArgument
590
+ def pre
591
+ [ "#{@callarg} = GirFFI::ArgHelper.pointer_to_inoutptr(GirFFI::ArgHelper.#{subtype_tag}_array_to_#{type_tag} #{@name})" ]
592
+ end
593
+
594
+ def post
595
+ elm_t = subtype_tag.inspect
596
+ pp = []
597
+ pp << "#{@retname} = GLib::SList.wrap #{elm_t}, GirFFI::ArgHelper.outptr_to_pointer(#{@callarg})"
598
+ pp << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
599
+ pp
600
+ end
601
+ end
602
+
603
+ # Implements argument processing for ghash arguments with direction
604
+ # :inout.
605
+ class HashTableInOutArgument < InOutArgument
606
+ def pre
607
+ key_t = subtype_tag(0).inspect
608
+ val_t = subtype_tag(1).inspect
609
+ [ "#{@callarg} = GirFFI::ArgHelper.pointer_to_inoutptr(GirFFI::ArgHelper.hash_to_ghash(#{key_t}, #{val_t}, #{@name}))" ]
610
+ end
611
+
612
+ def postpost
613
+ pp = []
614
+
615
+ key_t = subtype_tag(0).inspect
616
+ val_t = subtype_tag(1).inspect
617
+ pp << "#{@retname} = GLib::HashTable.wrap #{key_t}, #{val_t}, GirFFI::ArgHelper.outptr_to_pointer(#{@callarg})"
618
+ pp << "GirFFI::ArgHelper.cleanup_ptr #{@callarg}"
619
+ pp
620
+ end
621
+ end
622
+
623
+ # Implements argument processing for arguments with direction
624
+ # :inout that are neither arrays nor 'interfaces'.
625
+ class RegularInOutArgument < InOutArgument
370
626
  def pre
371
627
  pr = []
372
628
  if @array_arg
@@ -375,6 +631,11 @@ module GirFFI::Builder
375
631
  pr << "#{@callarg} = GirFFI::ArgHelper.#{type_tag}_to_inoutptr #{@name}"
376
632
  pr
377
633
  end
634
+
635
+ def post
636
+ [ "#{@retname} = GirFFI::ArgHelper.outptr_to_#{type_tag} #{@callarg}",
637
+ "GirFFI::ArgHelper.cleanup_ptr #{@callarg}" ]
638
+ end
378
639
  end
379
640
 
380
641
  # Implements argument processing for return values.
@@ -397,7 +658,7 @@ module GirFFI::Builder
397
658
  VoidReturnValue
398
659
  when :interface
399
660
  case type.interface.info_type
400
- when :interface, :struct
661
+ when :interface, :struct, :union
401
662
  InterfaceReturnValue
402
663
  when :object
403
664
  if arginfo.constructor?
@@ -409,9 +670,24 @@ module GirFFI::Builder
409
670
  RegularReturnValue
410
671
  end
411
672
  when :array
412
- ArrayReturnValue
413
- when :glist, :gslist
673
+ if type.zero_terminated?
674
+ StrvReturnValue
675
+ else
676
+ case type.array_type
677
+ when :c
678
+ CArrayReturnValue
679
+ when :array
680
+ ArrayReturnValue
681
+ when :byte_array
682
+ ByteArrayReturnValue
683
+ end
684
+ end
685
+ when :glist
414
686
  ListReturnValue
687
+ when :gslist
688
+ SListReturnValue
689
+ when :ghash
690
+ HashTableReturnValue
415
691
  else
416
692
  RegularReturnValue
417
693
  end
@@ -452,12 +728,12 @@ module GirFFI::Builder
452
728
  end
453
729
 
454
730
  def post
455
- [ "#{@retname} = #{defining_class_name}.constructor_wrap(#{@cvar})" ]
731
+ [ "#{@retname} = self.constructor_wrap(#{@cvar})" ]
456
732
  end
457
733
  end
458
734
 
459
735
  # Implements argument processing for array return values.
460
- class ArrayReturnValue < ReturnValue
736
+ class CArrayReturnValue < ReturnValue
461
737
  def post
462
738
  size = array_size
463
739
 
@@ -465,17 +741,67 @@ module GirFFI::Builder
465
741
  end
466
742
  end
467
743
 
468
- # Implements argument processing for GSList return values.
744
+ # Implements argument processing for NULL-terminated string array return values.
745
+ class StrvReturnValue < ReturnValue
746
+ def post
747
+ [ "#{@retname} = GirFFI::ArgHelper.strv_to_utf8_array #{@cvar}" ]
748
+ end
749
+ end
750
+
751
+ # Implements argument processing for GList return values.
469
752
  class ListReturnValue < ReturnValue
470
753
  def post
471
- [ "#{@retname} = GirFFI::ArgHelper.#{type_tag}_to_#{subtype_tag}_array #{@cvar}" ]
754
+ elm_t = subtype_tag.inspect
755
+ [ "#{@retname} = GLib::List.wrap(#{elm_t}, #{@cvar})" ]
756
+ end
757
+ end
758
+
759
+ # Implements argument processing for GSList return values.
760
+ class SListReturnValue < ReturnValue
761
+ def post
762
+ elm_t = subtype_tag.inspect
763
+ [ "#{@retname} = GLib::SList.wrap(#{elm_t}, #{@cvar})" ]
764
+ end
765
+ end
766
+
767
+ # Implements argument processing for GHashTable return values.
768
+ class HashTableReturnValue < ReturnValue
769
+ def post
770
+ key_t = subtype_tag(0).inspect
771
+ val_t = subtype_tag(1).inspect
772
+ [ "#{@retname} = GLib::HashTable.wrap(#{key_t}, #{val_t}, #{@cvar})" ]
773
+ end
774
+ end
775
+
776
+ # Implements argument processing for GHashTable return values.
777
+ class ByteArrayReturnValue < ReturnValue
778
+ def post
779
+ [ "#{@retname} = GLib::ByteArray.wrap(#{@cvar})" ]
780
+ end
781
+ end
782
+
783
+ # Implements argument processing for GHashTable return values.
784
+ class ArrayReturnValue < ReturnValue
785
+ def post
786
+ tag = subtype_tag
787
+ etype = GirFFI::Builder::TAG_TYPE_MAP[tag] || tag
788
+ [ "#{@retname} = GLib::Array.wrap(#{@cvar})",
789
+ "#{@retname}.element_type = #{etype.inspect}" ]
472
790
  end
473
791
  end
474
792
 
475
793
  # Implements argument processing for other return values.
476
794
  class RegularReturnValue < ReturnValue
477
795
  def retval
478
- @cvar
796
+ if RUBY_VERSION < "1.9"
797
+ @cvar
798
+ else
799
+ if type_tag == :utf8
800
+ "#{@cvar}.force_encoding('utf-8')"
801
+ else
802
+ @cvar
803
+ end
804
+ end
479
805
  end
480
806
  end
481
807
 
@@ -1,5 +1,6 @@
1
1
  require 'gir_ffi/builder_helper'
2
2
  require 'gir_ffi/module_base'
3
+ require 'gir_ffi/builder/function'
3
4
 
4
5
  module GirFFI
5
6
  # Builds a module based on information found in the introspection
@@ -38,9 +39,15 @@ module GirFFI
38
39
  Builder.build_class info
39
40
  end
40
41
 
41
- private
42
-
43
42
  def build_module
43
+ unless defined? @module
44
+ build_dependencies
45
+ build_module_non_recursive
46
+ end
47
+ @module
48
+ end
49
+
50
+ def build_module_non_recursive
44
51
  unless defined? @module
45
52
  instantiate_module
46
53
  setup_lib_for_ffi
@@ -49,6 +56,16 @@ module GirFFI
49
56
  @module
50
57
  end
51
58
 
59
+ private
60
+
61
+ def build_dependencies
62
+ deps = gir.dependencies @namespace
63
+ deps.each {|dep|
64
+ name, version = dep.split '-'
65
+ Builder.build_module_non_recursive name, version
66
+ }
67
+ end
68
+
52
69
  def instantiate_module
53
70
  @module = get_or_define_module ::Object, @safe_namespace
54
71
  end
@@ -72,9 +89,11 @@ module GirFFI
72
89
 
73
90
  unless (class << @lib; self.include? FFI::Library; end)
74
91
  @lib.extend FFI::Library
75
- libs = gir.shared_library(@namespace).split(/,/)
76
92
  @lib.ffi_lib_flags :global, :lazy
77
- @lib.ffi_lib(*libs)
93
+ libspec = gir.shared_library(@namespace)
94
+ unless libspec.nil?
95
+ @lib.ffi_lib(*libspec.split(/,/))
96
+ end
78
97
  end
79
98
 
80
99
  optionally_define_constant(@lib, :CALLBACKS) { [] }
@@ -82,12 +101,8 @@ module GirFFI
82
101
 
83
102
  def function_introspection_data function
84
103
  info = gir.find_by_name @namespace, function.to_s
85
-
86
- if info.info_type == :function
87
- info
88
- else
89
- nil
90
- end
104
+ return nil if info.nil?
105
+ info.info_type == :function ? info : nil
91
106
  end
92
107
 
93
108
  def function_definition info, libmodule
@@ -0,0 +1,39 @@
1
+ require 'gir_ffi/builder/type/base'
2
+ module GirFFI
3
+ module Builder
4
+ module Type
5
+
6
+ # Implements the creation of a constant. Though semantically not a
7
+ # type, its build method is like that of the types, in that it is
8
+ # triggered by a missing constant in the parent namespace. The
9
+ # constant will be attached to the appropriate namespace module.
10
+ class Constant < Base
11
+ TYPE_TAG_TO_UNION_MEMBER = {
12
+ :gint32 => :v_int32,
13
+ :gdouble => :v_double,
14
+ :utf8 => :v_string
15
+ }
16
+
17
+ def build_class
18
+ unless defined? @klass
19
+ instantiate_class
20
+ end
21
+ @klass
22
+ end
23
+
24
+ def instantiate_class
25
+ @klass = optionally_define_constant namespace_module, @classname do
26
+ tag = info.constant_type.tag
27
+ val = info.value[TYPE_TAG_TO_UNION_MEMBER[tag]]
28
+ if RUBY_VERSION >= "1.9" and tag == :utf8
29
+ val.force_encoding("utf-8")
30
+ else
31
+ val
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+