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
@@ -1,12 +1,13 @@
1
1
  module GObject
2
2
  load_class :Closure
3
3
 
4
+ # Overrides for GClosure, GObject's base class for closure objects.
4
5
  class Closure
5
6
  def set_marshal marshal
6
- _v1 = GirFFI::CallbackHelper.wrap_in_callback_args_mapper(
7
+ callback = GirFFI::CallbackHelper.wrap_in_callback_args_mapper(
7
8
  "GObject", "ClosureMarshal", marshal)
8
- ::GObject::Lib::CALLBACKS << _v1
9
- ::GObject::Lib.g_closure_set_marshal self, _v1
9
+ Lib::CALLBACKS << callback
10
+ Lib.g_closure_set_marshal self, callback
10
11
  end
11
12
  end
12
13
  end
@@ -1,12 +1,17 @@
1
1
  module GObject
2
2
  module Helper
3
- TAG_TYPE_TO_GTYPE_NAME_MAP = {
4
- :utf8 => "gchararray",
5
- :gboolean => "gboolean",
6
- :void => "void"
7
- }
3
+ def self.signal_callback klass, signal, &block
4
+ sig = klass._find_signal signal
5
+
6
+ rettype = GirFFI::Builder.itypeinfo_to_ffitype sig.return_type
7
+ argtypes = GirFFI::Builder.ffi_argument_types_for_signal sig
8
+ callback_block = Helper.signal_callback_args(sig, klass, &block)
9
+
10
+ FFI::Function.new rettype, argtypes, &callback_block
11
+ end
8
12
 
9
13
  def self.signal_callback_args sig, klass, &block
14
+ raise ArgumentError, "Block needed" if block.nil?
10
15
  return Proc.new do |*args|
11
16
  mapped = cast_back_signal_arguments sig, klass, *args
12
17
  block.call(*mapped)
@@ -35,27 +40,8 @@ module GObject
35
40
  end
36
41
 
37
42
  def self.signal_argument_to_gvalue info, arg
38
- arg_type = info.argument_type
39
-
40
- val = gvalue_for_type_info arg_type
41
-
42
- if arg_type.tag == :interface
43
- interface = arg_type.interface
44
- case interface.info_type
45
- when :struct
46
- val.set_boxed arg
47
- when :object
48
- val.set_instance arg
49
- when :enum
50
- val.set_enum arg
51
- else
52
- raise NotImplementedError, interface.info_type
53
- end
54
- else
55
- val.set_ruby_value arg
56
- end
57
-
58
- return val
43
+ val = gvalue_for_type_info info.argument_type
44
+ val.set_value arg
59
45
  end
60
46
 
61
47
  def self.gvalue_for_type_info info
@@ -66,9 +52,10 @@ module GObject
66
52
  when :void
67
53
  return nil
68
54
  else
69
- ::GObject.type_from_name(TAG_TYPE_TO_GTYPE_NAME_MAP[tag])
55
+ TYPE_TAG_TO_GTYPE[tag]
70
56
  end
71
- ::GObject::Value.new.tap {|val| val.init gtype}
57
+ raise "GType not found for type info with tag #{tag}" unless gtype
58
+ Value.new.tap {|val| val.init gtype}
72
59
  end
73
60
 
74
61
  def self.gvalue_for_signal_return_value signal, object
@@ -80,24 +67,14 @@ module GObject
80
67
 
81
68
  # TODO: Generate cast back methods using existing Argument builders.
82
69
  def self.cast_back_signal_arguments signalinfo, klass, *args
83
- result = []
70
+ instance = klass.wrap args.shift
71
+ user_data = GirFFI::ArgHelper::OBJECT_STORE[args.pop.address]
84
72
 
85
- # Instance
86
- instptr = args.shift
87
- instance = klass.wrap instptr
88
- result << instance
89
-
90
- # Extra arguments
91
- signalinfo.args.each do |info|
92
- result << cast_signal_argument(info, args.shift)
73
+ extra_arguments = signalinfo.args.zip(args).map do |info, arg|
74
+ cast_signal_argument(info, arg)
93
75
  end
94
76
 
95
- # User Data
96
- arg = args.shift
97
- arg = GirFFI::ArgHelper::OBJECT_STORE[arg.address]
98
- result << arg
99
-
100
- return result
77
+ return [instance, *extra_arguments].push user_data
101
78
  end
102
79
 
103
80
  def self.cast_signal_argument info, arg
@@ -1,6 +1,8 @@
1
1
  module GObject
2
2
  load_class :InitiallyUnowned
3
3
 
4
+ # Overrides for GInitiallyUnowned, GObject's base class for objects that
5
+ # start with a floating reference.
4
6
  class InitiallyUnowned
5
7
  def self.constructor_wrap ptr
6
8
  super.tap {|obj| ::GObject.object_ref_sink obj}
@@ -0,0 +1,54 @@
1
+ module GObject
2
+ load_class :Object
3
+
4
+ # Overrides for GObject, GObject's generic base class.
5
+ class Object
6
+ _setup_instance_method "get_property"
7
+ _setup_instance_method "set_property"
8
+
9
+ def get_property_with_override property_name
10
+ prop = self.class._find_property property_name
11
+ type = prop.property_type
12
+ v = Helper.gvalue_for_type_info type
13
+ get_property_without_override property_name, v
14
+
15
+ val = v.ruby_value
16
+ case type.tag
17
+ when :ghash
18
+ GLib::HashTable.wrap type.param_type(0).tag, type.param_type(1).tag,
19
+ val.to_ptr
20
+ when :glist
21
+ GLib::List.wrap type.param_type(0).tag, val
22
+ else
23
+ val
24
+ end
25
+ end
26
+
27
+ def set_property_with_override property_name, value
28
+ prop = self.class._find_property property_name
29
+ type = prop.property_type
30
+ v = Helper.gvalue_for_type_info type
31
+
32
+ case type.tag
33
+ when :glist
34
+ lst = GLib::List.from_array type.param_type(0).tag, value
35
+ v.set_value lst.to_ptr
36
+ when :ghash
37
+ hsh = GLib::HashTable.from_hash type.param_type(0).tag,
38
+ type.param_type(1).tag, value
39
+ v.set_value hsh.to_ptr
40
+ else
41
+ v.set_value value
42
+ end
43
+
44
+ set_property_without_override property_name, v
45
+ end
46
+
47
+ alias get_property_without_override get_property
48
+ alias get_property get_property_with_override
49
+
50
+ alias set_property_without_override set_property
51
+ alias set_property set_property_with_override
52
+ end
53
+ end
54
+
@@ -6,13 +6,21 @@ module GObject
6
6
  class RubyClosure < Closure
7
7
  BLOCK_STORE = {}
8
8
 
9
+ # Extend the standard GClosure layout with a field block_id to store
10
+ # the object_id of the associated block.
9
11
  class Struct < FFI::Struct
10
12
  layout :parent, Closure::Struct, 0,
11
- :blockhash, :int64
13
+ :block_id, :int64
12
14
  end
13
15
 
14
16
  def block
15
- self.class::BLOCK_STORE[self[:blockhash]]
17
+ BLOCK_STORE[@struct[:block_id]]
18
+ end
19
+
20
+ def block= block
21
+ id = block.object_id
22
+ BLOCK_STORE[id] = block
23
+ @struct[:block_id] = id
16
24
  end
17
25
 
18
26
  def invoke_block *args
@@ -21,27 +29,25 @@ module GObject
21
29
 
22
30
  def self.new &block
23
31
  raise ArgumentError unless block_given?
24
- wrap(new_simple(self::Struct.size, nil).to_ptr).tap do |it|
25
- h = block.object_id
26
- self::BLOCK_STORE[h] = block
27
- it[:blockhash] = h
28
- it.set_marshal Proc.new {|*args| marshaller(*args)}
29
- end
32
+
33
+ closure = wrap(new_simple(self::Struct.size, nil).to_ptr)
34
+ closure.block = block
35
+ closure.set_marshal Proc.new {|*args| marshaller(*args)}
36
+
37
+ return closure
30
38
  end
31
39
 
32
40
  def self.marshaller(closure, return_value, n_param_values,
33
41
  param_values, invocation_hint, marshal_data)
34
- rclosure = self.wrap(closure.to_ptr)
42
+ rclosure = wrap(closure.to_ptr)
35
43
 
36
- args = []
37
- n_param_values.times {|i|
38
- gv = ::GObject::Value.wrap(param_values.to_ptr +
39
- i * ::GObject::Value::Struct.size)
40
- args << gv.ruby_value
44
+ args = n_param_values.times.map {|idx|
45
+ Value.wrap(param_values.to_ptr + idx * Value::Struct.size).ruby_value
41
46
  }
42
47
 
43
- r = rclosure.invoke_block(*args)
44
- return_value.set_ruby_value r unless return_value.nil?
48
+ result = rclosure.invoke_block(*args)
49
+
50
+ return_value.set_ruby_value(result) unless return_value.nil?
45
51
  end
46
52
  end
47
53
  end
@@ -1,21 +1,38 @@
1
1
  module GObject
2
2
  load_class :Value
3
3
 
4
+ # Overrides for GValue, GObject's generic value container structure.
4
5
  class Value
5
6
  def set_ruby_value val
6
7
  if current_gtype == 0
7
8
  init_for_ruby_value val
8
9
  end
9
10
 
10
- case current_gtype_name
11
- when "gboolean"
11
+ set_value val
12
+ end
13
+
14
+ def set_value val
15
+ case current_fundamental_type
16
+ when TYPE_BOOLEAN
12
17
  set_boolean val
13
- when "gint"
18
+ when TYPE_INT
14
19
  set_int val
15
- when "gchararray"
20
+ when TYPE_STRING
16
21
  set_string val
22
+ when TYPE_FLOAT
23
+ set_float val
24
+ when TYPE_DOUBLE
25
+ set_double val
26
+ when TYPE_BOXED
27
+ set_boxed val
28
+ when TYPE_OBJECT
29
+ set_instance val
30
+ when TYPE_POINTER
31
+ set_pointer val
32
+ when TYPE_ENUM
33
+ set_enum val
17
34
  else
18
- nil
35
+ raise "Don't know how to handle #{current_gtype_name}"
19
36
  end
20
37
  self
21
38
  end
@@ -23,36 +40,54 @@ module GObject
23
40
  def init_for_ruby_value val
24
41
  case val
25
42
  when true, false
26
- init ::GObject.type_from_name("gboolean")
43
+ init TYPE_BOOLEAN
27
44
  when Integer
28
- init ::GObject.type_from_name("gint")
45
+ init TYPE_INT
29
46
  end
30
47
  self
31
48
  end
32
49
 
33
50
  def current_gtype
34
- self[:g_type]
51
+ @struct[:g_type]
52
+ end
53
+
54
+ def current_fundamental_type
55
+ GObject.type_fundamental current_gtype
35
56
  end
36
57
 
37
58
  def current_gtype_name
38
- ::GObject.type_name current_gtype
59
+ GObject.type_name current_gtype
39
60
  end
40
61
 
41
62
  def ruby_value
42
- case current_gtype_name.to_sym
43
- when :gboolean
63
+ case current_fundamental_type
64
+ when TYPE_BOOLEAN
44
65
  get_boolean
45
- when :gint
66
+ when TYPE_INT
46
67
  get_int
47
- when :gchararray
68
+ when TYPE_STRING
48
69
  get_string
49
- when :GDate
50
- ::GLib::Date.wrap(get_boxed)
51
- when :GStrv
52
- # FIXME: Extract this method to even lower level module.
53
- GirFFI::ArgHelper.strv_to_utf8_array get_boxed
70
+ when TYPE_FLOAT
71
+ get_float
72
+ when TYPE_DOUBLE
73
+ get_double
74
+ when TYPE_OBJECT
75
+ get_object
76
+ when TYPE_BOXED
77
+ boxed = get_boxed
78
+ case current_gtype_name.to_sym
79
+ when :GStrv
80
+ # FIXME: Extract this method to even lower level module.
81
+ GirFFI::ArgHelper.strv_to_utf8_array boxed
82
+ when :GHashTable
83
+ GLib::HashTable.wrap :gpointer, :gpointer, boxed
84
+ else
85
+ GirFFI::ArgHelper.wrap_object_pointer_by_gtype boxed, current_gtype
86
+ end
87
+ when TYPE_POINTER
88
+ get_pointer
54
89
  else
55
- nil
90
+ raise "Don't know how to handle #{current_gtype_name}"
56
91
  end
57
92
  end
58
93
 
@@ -1,12 +1,28 @@
1
1
  module GObjectIntrospection
2
2
  # Wraps a GIConstantInfo struct; represents an constant.
3
3
  class IConstantInfo < IBaseInfo
4
- def value
4
+ TYPE_TAG_TO_UNION_MEMBER = {
5
+ :gint32 => :v_int32,
6
+ :gdouble => :v_double,
7
+ :utf8 => :v_string
8
+ }
9
+
10
+ def value_union
5
11
  val = Lib::GIArgument.new
6
12
  Lib.g_constant_info_get_value @gobj, val
7
13
  return val
8
14
  end
9
15
 
16
+ def value
17
+ tag = constant_type.tag
18
+ val = value_union[TYPE_TAG_TO_UNION_MEMBER[tag]]
19
+ if RUBY_VERSION >= "1.9" and tag == :utf8
20
+ val.force_encoding("utf-8")
21
+ else
22
+ val
23
+ end
24
+ end
25
+
10
26
  def constant_type
11
27
  ITypeInfo.wrap(Lib.g_constant_info_get_type @gobj)
12
28
  end
@@ -17,5 +17,13 @@ module GObjectIntrospection
17
17
  def field_type
18
18
  ITypeInfo.wrap(Lib.g_field_info_get_type @gobj)
19
19
  end
20
+
21
+ def readable?
22
+ flags & 1 != 0
23
+ end
24
+
25
+ def writable?
26
+ flags & 2 != 0
27
+ end
20
28
  end
21
29
  end
@@ -1,7 +1,9 @@
1
1
  module GObjectIntrospection
2
2
  # Wraps a GIPropertyInfo struct.
3
3
  # Represents a property of an IObjectInfo or an IInterfaceInfo.
4
- # Not implemented yet.
5
4
  class IPropertyInfo < IBaseInfo
5
+ def property_type
6
+ ITypeInfo.wrap(Lib.g_property_info_get_type @gobj)
7
+ end
6
8
  end
7
9
  end
@@ -3,7 +3,19 @@ require 'ffi'
3
3
  module GObjectIntrospection
4
4
  module Lib
5
5
  extend FFI::Library
6
- ffi_lib "girepository-1.0"
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
7
19
 
8
20
  # IRepository
9
21
  enum :IRepositoryLoadFlags, [:LAZY, (1<<0)]
@@ -148,7 +160,8 @@ module GObjectIntrospection
148
160
  :readable, (1 << 0),
149
161
  :writable, (1 << 1)
150
162
  ]
151
- attach_function :g_field_info_get_flags, [:pointer], :IFieldInfoFlags
163
+ # TODO: return type is bitfield :IFieldInfoFlags
164
+ attach_function :g_field_info_get_flags, [:pointer], :int
152
165
  attach_function :g_field_info_get_size, [:pointer], :int
153
166
  attach_function :g_field_info_get_offset, [:pointer], :int
154
167
  attach_function :g_field_info_get_type, [:pointer], :pointer
@@ -253,5 +266,9 @@ module GObjectIntrospection
253
266
  #
254
267
  attach_function :g_constant_info_get_type, [:pointer], :pointer
255
268
  attach_function :g_constant_info_get_value, [:pointer, :pointer], :int
269
+
270
+ # IPropertyInfo
271
+ #
272
+ attach_function :g_property_info_get_type, [:pointer], :pointer
256
273
  end
257
274
  end