gir_ffi 0.1.0 → 0.2.0

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