gir_ffi 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
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
+