gir_ffi 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/History.txt +8 -0
  2. data/lib/ffi-glib/array.rb +1 -1
  3. data/lib/ffi-glib.rb +7 -12
  4. data/lib/ffi-gobject/closure.rb +1 -4
  5. data/lib/ffi-gobject/object.rb +2 -2
  6. data/lib/ffi-gobject/ruby_style.rb +2 -0
  7. data/lib/ffi-gobject/value.rb +19 -1
  8. data/lib/ffi-gobject.rb +14 -9
  9. data/lib/ffi-gobject_introspection/i_base_info.rb +5 -5
  10. data/lib/ffi-gobject_introspection/i_repository.rb +1 -1
  11. data/lib/ffi-gobject_introspection/lib.rb +1 -1
  12. data/lib/gir_ffi/arg_helper.rb +3 -3
  13. data/lib/gir_ffi/argument_builder.rb +21 -17
  14. data/lib/gir_ffi/base_argument_builder.rb +5 -3
  15. data/lib/gir_ffi/builder/type/object.rb +1 -0
  16. data/lib/gir_ffi/builder/type/user_defined.rb +2 -3
  17. data/lib/gir_ffi/builder.rb +2 -2
  18. data/lib/gir_ffi/builder_helper.rb +2 -2
  19. data/lib/gir_ffi/callback_helper.rb +9 -9
  20. data/lib/gir_ffi/function_builder.rb +2 -2
  21. data/lib/gir_ffi/in_out_pointer.rb +1 -3
  22. data/lib/gir_ffi/in_pointer.rb +15 -2
  23. data/lib/gir_ffi/info_ext/i_arg_info.rb +27 -0
  24. data/lib/gir_ffi/info_ext/i_field_info.rb +1 -0
  25. data/lib/gir_ffi/info_ext/i_property_info.rb +1 -0
  26. data/lib/gir_ffi/info_ext/i_registered_type_info.rb +1 -1
  27. data/lib/gir_ffi/info_ext/i_signal_info.rb +65 -0
  28. data/lib/gir_ffi/info_ext/i_type_info.rb +15 -0
  29. data/lib/gir_ffi/info_ext/safe_constant_name.rb +1 -0
  30. data/lib/gir_ffi/info_ext/safe_function_name.rb +1 -0
  31. data/lib/gir_ffi/info_ext.rb +2 -0
  32. data/lib/gir_ffi/module_base.rb +1 -3
  33. data/lib/gir_ffi/return_value_builder.rb +1 -4
  34. data/lib/gir_ffi/version.rb +1 -2
  35. data/lib/gir_ffi/zero_terminated.rb +42 -0
  36. data/lib/gir_ffi.rb +1 -0
  37. data/test/ffi-gobject/value_test.rb +30 -1
  38. data/test/ffi-gobject_introspection/i_object_info_test.rb +4 -4
  39. data/test/ffi-gobject_test.rb +20 -0
  40. data/test/gir_ffi/arg_helper_test.rb +4 -4
  41. data/test/gir_ffi/argument_builder_test.rb +16 -0
  42. data/test/gir_ffi/builder_test.rb +0 -5
  43. data/test/gir_ffi/in_pointer_test.rb +20 -1
  44. data/test/gir_ffi/info_ext/i_arg_info_test.rb +39 -0
  45. data/test/gir_ffi/info_ext/i_signal_info_test.rb +51 -0
  46. data/test/gir_ffi/info_ext/i_type_info_test.rb +20 -20
  47. data/test/gir_ffi/return_value_builder_test.rb +2 -2
  48. data/test/gir_ffi/zero_terminated_test.rb +48 -0
  49. data/test/gir_ffi_test_helper.rb +3 -3
  50. data/test/integration/generated_gimarshallingtests_test.rb +38 -28
  51. data/test/integration/generated_regress_test.rb +2 -5
  52. metadata +11 -5
  53. data/lib/ffi-gobject/helper.rb +0 -114
  54. data/test/ffi-gobject/helper_test.rb +0 -103
data/History.txt CHANGED
@@ -1,3 +1,11 @@
1
+ == 0.5.2 / 2013-04-23
2
+
3
+ * Handle signal details in GObject.signal_connect and .signal_emit
4
+ * Make GValue#set_value check object GType compatibility
5
+ * Eliminate GObject::Helper module
6
+ * Handle more argument types
7
+ * Support Ruby 2.0.0
8
+
1
9
  == 0.5.1 / 2013-02-01
2
10
 
3
11
  * Properly handle zero-terminated arrays of :filename
@@ -40,7 +40,7 @@ module GLib
40
40
  end
41
41
 
42
42
  def get_element_size
43
- GLib.array_get_element_size self
43
+ Lib.g_array_get_element_size self
44
44
  end
45
45
 
46
46
  def self.wrap elmttype, ptr
data/lib/ffi-glib.rb CHANGED
@@ -22,24 +22,19 @@ module GLib
22
22
 
23
23
  attach_function :g_list_append, [:pointer, :pointer], :pointer
24
24
 
25
- attach_function :g_hash_table_foreach,
26
- [:pointer, HFunc, :pointer], :void
27
- attach_function :g_hash_table_new,
28
- [HashFunc, EqualFunc], :pointer
29
- attach_function :g_hash_table_insert,
30
- [:pointer, :pointer, :pointer], :void
25
+ attach_function :g_hash_table_foreach, [:pointer, HFunc, :pointer], :void
26
+ attach_function :g_hash_table_new, [HashFunc, EqualFunc], :pointer
27
+ attach_function :g_hash_table_insert, [:pointer, :pointer, :pointer], :void
31
28
 
32
29
  attach_function :g_byte_array_new, [], :pointer
33
- attach_function :g_byte_array_append,
34
- [:pointer, :pointer, :uint], :pointer
30
+ attach_function :g_byte_array_append, [:pointer, :pointer, :uint], :pointer
35
31
 
36
32
  attach_function :g_array_new, [:int, :int, :uint], :pointer
37
- attach_function :g_array_append_vals,
38
- [:pointer, :pointer, :uint], :pointer
33
+ attach_function :g_array_append_vals, [:pointer, :pointer, :uint], :pointer
34
+ attach_function :g_array_get_element_size, [:pointer], :uint
39
35
 
40
36
  attach_function :g_ptr_array_new, [], :pointer
41
37
  attach_function :g_ptr_array_add, [:pointer, :pointer], :void
42
- attach_function :g_ptr_array_foreach, [:pointer, Func, :pointer],
43
- :pointer
38
+ attach_function :g_ptr_array_foreach, [:pointer, Func, :pointer], :pointer
44
39
  end
45
40
  end
@@ -4,10 +4,7 @@ module GObject
4
4
  # Overrides for GClosure, GObject's base class for closure objects.
5
5
  class Closure
6
6
  def set_marshal marshal
7
- callback = GirFFI::CallbackHelper.wrap_in_callback_args_mapper("GObject",
8
- "ClosureMarshal",
9
- marshal)
10
- GirFFI::CallbackHelper.store_callback callback
7
+ callback = GirFFI::Callback.from("GObject", "ClosureMarshal", marshal)
11
8
  Lib.g_closure_set_marshal self, callback
12
9
  end
13
10
  end
@@ -14,7 +14,7 @@ module GObject
14
14
 
15
15
  def get_property_with_override property_name
16
16
  type = get_property_type property_name
17
- gvalue = Helper.gvalue_for_type_info type
17
+ gvalue = type.make_g_value
18
18
 
19
19
  get_property_without_override property_name, gvalue
20
20
 
@@ -23,7 +23,7 @@ module GObject
23
23
 
24
24
  def set_property_with_override property_name, value
25
25
  type = get_property_type property_name
26
- gvalue = Helper.gvalue_for_type_info type
26
+ gvalue = type.make_g_value
27
27
 
28
28
  gvalue.set_value adjust_value_to_type(value, type)
29
29
 
@@ -2,6 +2,7 @@ module GObject
2
2
 
3
3
  module RubyStyle
4
4
 
5
+ # TODO: Generate accessor methods from GIR at class definition time
5
6
  def method_missing(method, *args)
6
7
  if respond_to?("get_#{method}")
7
8
  return send("get_#{method}", *args)
@@ -12,6 +13,7 @@ module GObject
12
13
  super
13
14
  end
14
15
 
16
+ # TODO: Move to definition of GObject::Object
15
17
  def signal_connect(event, &block)
16
18
  GObject.signal_connect(self, event, &block)
17
19
  end
@@ -17,7 +17,8 @@ module GObject
17
17
  TYPE_STRING => :set_string,
18
18
  TYPE_FLOAT => :set_float,
19
19
  TYPE_DOUBLE => :set_double,
20
- TYPE_OBJECT => :set_instance,
20
+ TYPE_PARAM => :set_param,
21
+ TYPE_OBJECT => :set_instance_enhanced,
21
22
  TYPE_BOXED => :set_boxed,
22
23
  TYPE_POINTER => :set_pointer,
23
24
  TYPE_ENUM => :set_enum
@@ -89,10 +90,27 @@ module GObject
89
90
  wrap_ruby_value val
90
91
  end
91
92
  end
93
+
94
+ def for_g_type g_type
95
+ return nil if g_type == TYPE_NONE
96
+ self.new.tap {|it| it.init g_type }
97
+ end
92
98
  end
93
99
 
94
100
  private
95
101
 
102
+ def set_instance_enhanced val
103
+ check_type_compatibility val
104
+ set_instance val
105
+ end
106
+
107
+ def check_type_compatibility val
108
+ return if val.nil?
109
+ if !GObject::Value.type_compatible(GObject.type_from_instance(val), current_gtype)
110
+ raise ArgumentError, "#{val.class} is incompatible with #{current_gtype_name}"
111
+ end
112
+ end
113
+
96
114
  def get_boxed_enhanced
97
115
  boxed = get_boxed
98
116
  case current_gtype
data/lib/ffi-gobject.rb CHANGED
@@ -10,7 +10,6 @@ require 'ffi-gobject/initially_unowned'
10
10
  require 'ffi-gobject/closure'
11
11
  require 'ffi-gobject/object'
12
12
  require 'ffi-gobject/ruby_closure'
13
- require 'ffi-gobject/helper'
14
13
  require 'gir_ffi/builder/type/user_defined'
15
14
 
16
15
  module GObject
@@ -60,22 +59,28 @@ module GObject
60
59
  signal_lookup signal, type_from_instance(object)
61
60
  end
62
61
 
63
- def self.signal_emit object, signal, *args
62
+ def self.signal_emit object, detailed_signal, *args
63
+ signal, detail = detailed_signal.split('::')
64
+ sig_info = object.class.find_signal signal
65
+
64
66
  id = signal_lookup_from_instance signal, object
65
- arr = Helper.signal_arguments_to_gvalue_array signal, object, *args
66
- rval = Helper.gvalue_for_signal_return_value signal, object
67
+ detail_quark = GLib.quark_from_string(detail)
68
+
69
+ arr = sig_info.signal_arguments_to_gvalue_array object, *args
70
+ rval = sig_info.gvalue_for_signal_return_value
67
71
 
68
- Lib.g_signal_emitv arr.values, id, 0, rval
72
+ Lib.g_signal_emitv arr.values, id, detail_quark, rval
69
73
 
70
74
  return rval
71
75
  end
72
76
 
73
- def self.signal_connect object, signal, data=nil, &block
74
- callback = Helper.signal_callback object.class, signal, &block
77
+ def self.signal_connect object, detailed_signal, data=nil, &block
78
+ signal, _ = detailed_signal.split('::')
79
+ sig_info = object.class.find_signal signal
80
+ callback = sig_info.signal_callback(&block)
75
81
  GirFFI::CallbackHelper.store_callback callback
76
82
  data_ptr = GirFFI::ArgHelper.object_to_inptr data
77
-
78
- Lib.g_signal_connect_data object, signal, callback, data_ptr, nil, 0
83
+ Lib.g_signal_connect_data object, detailed_signal, callback, data_ptr, nil, 0
79
84
  end
80
85
 
81
86
  def self.param_spec_int(name, nick, blurb, minimum, maximum,
@@ -33,11 +33,11 @@ module GObjectIntrospection
33
33
  single ||= method[0..-2]
34
34
  count = method.sub(/^(get_)?/, "\\1n_")
35
35
  self.class_eval <<-CODE
36
- def #{method}
37
- (0..(#{count} - 1)).map do |i|
38
- #{single} i
39
- end
40
- end
36
+ def #{method}
37
+ (0..(#{count} - 1)).map do |i|
38
+ #{single} i
39
+ end
40
+ end
41
41
  CODE
42
42
  end
43
43
 
@@ -95,7 +95,7 @@ module GObjectIntrospection
95
95
  # Utility method
96
96
  def infos namespace
97
97
  (0..(n_infos(namespace) - 1)).map do |idx|
98
- info namespace, idx
98
+ info namespace, idx
99
99
  end
100
100
  end
101
101
 
@@ -168,7 +168,7 @@ module GObjectIntrospection
168
168
  attach_function :g_union_info_find_method, [:pointer, :string], :pointer
169
169
  attach_function :g_union_info_get_size, [:pointer], :int
170
170
  attach_function :g_union_info_get_alignment, [:pointer], :int
171
-
171
+
172
172
  # IRegisteredTypeInfo
173
173
  attach_function :g_registered_type_info_get_type_name, [:pointer], :string
174
174
  attach_function :g_registered_type_info_get_type_init, [:pointer], :string
@@ -17,8 +17,8 @@ module GirFFI
17
17
  # FIXME: Hideous
18
18
  # TODO: Move this implementation to InPointer
19
19
  def self.object_to_inptr obj
20
- return obj.to_ptr if obj.respond_to? :to_ptr
21
20
  return nil if obj.nil?
21
+ return obj.to_ptr if obj.respond_to? :to_ptr
22
22
  return obj if obj.is_a? FFI::Pointer
23
23
 
24
24
  FFI::Pointer.new(obj.object_id).tap {|ptr|
@@ -96,12 +96,12 @@ module GirFFI
96
96
 
97
97
  def self.check_error errpp
98
98
  err = GLib::Error.wrap(errpp.read_pointer)
99
- raise err.message unless err.nil?
99
+ raise err.message if err
100
100
  end
101
101
 
102
102
  def self.check_fixed_array_size size, arr, name
103
103
  unless arr.size == size
104
- raise ArgumentError, "#{name} should have size #{size}"
104
+ raise ArgumentError, "#{name} should have size #{size}"
105
105
  end
106
106
  end
107
107
 
@@ -31,29 +31,33 @@ module GirFFI
31
31
  end
32
32
 
33
33
  def post
34
- result = []
35
34
  if has_output_value?
36
- value = if is_caller_allocated_object?
37
- callarg
38
- elsif needs_outgoing_parameter_conversion?
39
- case specialized_type_tag
40
- when :enum, :flags
41
- "#{argument_class_name}[#{output_conversion_arguments}]"
42
- else
43
- "#{argument_class_name}.wrap(#{output_conversion_arguments})"
44
- end
45
- elsif is_fixed_length_array?
46
- "#{callarg}.to_sized_array_value #{array_size}"
47
- else
48
- "#{callarg}.to_value"
49
- end
50
- result << "#{retname} = #{value}"
35
+ value = output_value
36
+ ["#{retname} = #{value}"]
37
+ else
38
+ []
51
39
  end
52
- result
53
40
  end
54
41
 
55
42
  private
56
43
 
44
+ def output_value
45
+ if is_caller_allocated_object?
46
+ callarg
47
+ elsif needs_outgoing_parameter_conversion?
48
+ case specialized_type_tag
49
+ when :enum, :flags
50
+ "#{argument_class_name}[#{output_conversion_arguments}]"
51
+ else
52
+ "#{argument_class_name}.wrap(#{output_conversion_arguments})"
53
+ end
54
+ elsif is_fixed_length_array?
55
+ "#{callarg}.to_sized_array_value #{array_size}"
56
+ else
57
+ "#{callarg}.to_value"
58
+ end
59
+ end
60
+
57
61
  def is_array_length_parameter?
58
62
  @array_arg
59
63
  end
@@ -68,8 +68,10 @@ module GirFFI
68
68
  'GLib::PtrArray'
69
69
  when :strv
70
70
  'GLib::Strv'
71
- when :c, :zero_terminated
71
+ when :c
72
72
  'GirFFI::InPointer'
73
+ when :zero_terminated
74
+ 'GirFFI::ZeroTerminated'
73
75
  else
74
76
  TAG_TO_WRAPPER_CLASS_MAP[tag]
75
77
  end
@@ -129,9 +131,9 @@ module GirFFI
129
131
  case specialized_type_tag
130
132
  when :utf8, :void
131
133
  "#{self_t}, #{name}"
132
- when :glist, :gslist, :ghash, :array
134
+ when :glist, :gslist, :ghash, :array, :zero_terminated
133
135
  "#{elm_t}, #{name}"
134
- when :c, :zero_terminated
136
+ when :c
135
137
  "#{type_specification}, #{name}"
136
138
  when :callback
137
139
  iface = type_info.interface
@@ -83,6 +83,7 @@ module GirFFI
83
83
  @klass.class_eval builder.setter_def
84
84
  end
85
85
 
86
+ # TODO: Guard agains accidental invocation of undefined vfuncs.
86
87
  def setup_vfunc_invokers
87
88
  info.vfuncs.each do |vfinfo|
88
89
  invoker = vfinfo.invoker
@@ -30,10 +30,9 @@ module GirFFI
30
30
  type_info.instance_size += FFI.type_size(:int32)
31
31
  end
32
32
 
33
- new_type = GObject.type_register_static parent_type, @klass.name, type_info, 0
33
+ @gtype = GObject.type_register_static(parent_type, @klass.name,
34
+ type_info, 0)
34
35
 
35
- # TODO: Check that class ultimately derives from GObject.
36
- @gtype = new_type
37
36
  @structklass = get_or_define_class @klass, :Struct, layout_superclass
38
37
  setup_class unless already_set_up
39
38
  CACHE[@gtype] = @klass
@@ -52,8 +52,8 @@ module GirFFI
52
52
  types = info.args.map { |arg| iarginfo_to_ffitype arg }
53
53
 
54
54
  if info.info_type == :function
55
- types.unshift :pointer if info.method?
56
- types << :pointer if info.throws?
55
+ types.unshift :pointer if info.method?
56
+ types << :pointer if info.throws?
57
57
  end
58
58
 
59
59
  types
@@ -2,9 +2,9 @@ module GirFFI
2
2
  module BuilderHelper
3
3
  def const_defined_for parent, name
4
4
  if RUBY_VERSION < "1.9"
5
- parent.const_defined? name
5
+ parent.const_defined? name
6
6
  else
7
- parent.const_defined? name, false
7
+ parent.const_defined? name, false
8
8
  end
9
9
  end
10
10
 
@@ -8,13 +8,13 @@ module GirFFI
8
8
  return nil if prc.nil?
9
9
  info = GObjectIntrospection::IRepository.default.find_by_name namespace, name
10
10
  return Callback.new do |*args|
11
- prc.call(*map_callback_args(args, info))
11
+ prc.call(*map_callback_args(args, info))
12
12
  end
13
13
  end
14
14
 
15
15
  def self.map_callback_args args, info
16
16
  args.zip(info.args).map { |arg, inf|
17
- map_single_callback_arg arg, inf.argument_type }
17
+ map_single_callback_arg arg, inf.argument_type }
18
18
  end
19
19
 
20
20
  # TODO: Use GirFFI::ReturnValue classes for mapping.
@@ -23,18 +23,18 @@ module GirFFI
23
23
  when :interface
24
24
  map_interface_callback_arg arg, type
25
25
  when :utf8
26
- ArgHelper.ptr_to_utf8 arg
26
+ ArgHelper.ptr_to_utf8 arg
27
27
  when :void
28
28
  map_void_callback_arg arg
29
29
  when :array
30
- subtype = type.param_type(0)
30
+ subtype = type.param_type(0)
31
31
  if subtype.tag == :interface and arg.is_a?(FFI::Pointer)
32
- map_interface_callback_arg arg, subtype
33
- else
34
- raise NotImplementedError
35
- end
32
+ map_interface_callback_arg arg, subtype
33
+ else
34
+ raise NotImplementedError
35
+ end
36
36
  else
37
- arg
37
+ arg
38
38
  end
39
39
  end
40
40
 
@@ -22,9 +22,9 @@ module GirFFI
22
22
  alldata = @data.dup << @rvdata
23
23
 
24
24
  alldata.each {|data|
25
- idx = data.type_info.array_length
25
+ idx = data.type_info.array_length
26
26
  if idx > -1
27
- data.length_arg = @data[idx]
27
+ data.length_arg = @data[idx]
28
28
  @data[idx].array_arg = data
29
29
  end
30
30
  }
@@ -57,15 +57,13 @@ module GirFFI
57
57
  private
58
58
 
59
59
  def adjust_value_in value
60
- return nil_value if value.nil?
61
-
62
60
  case @value_type
63
61
  when :gboolean
64
62
  (value ? 1 : 0)
65
63
  when :utf8
66
64
  InPointer.from :utf8, value
67
65
  else
68
- value
66
+ value || nil_value
69
67
  end
70
68
  end
71
69
 
@@ -10,8 +10,14 @@ module GirFFI
10
10
  from_utf8_array ary
11
11
  when :interface_pointer
12
12
  from_interface_pointer_array ary
13
- else
13
+ when Symbol
14
14
  from_basic_type_array type, ary
15
+ when FFI::Enum
16
+ from_enum_array type, ary
17
+ when Array
18
+ from_interface_pointer_array ary
19
+ else
20
+ raise NotImplementedError, type
15
21
  end
16
22
  end
17
23
 
@@ -49,6 +55,10 @@ module GirFFI
49
55
  self.from_array :pointer, ptr_ary
50
56
  end
51
57
 
58
+ def from_enum_array type, ary
59
+ self.from_array :int32, ary.map {|sym| type.to_native sym, nil }
60
+ end
61
+
52
62
  def from_utf8 str
53
63
  len = str.bytesize
54
64
  ptr = AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0)
@@ -57,8 +67,11 @@ module GirFFI
57
67
 
58
68
  def from_basic_type_array type, ary
59
69
  ffi_type = TypeMap.map_basic_type type
60
- block = ArgHelper.allocate_array_of_type ffi_type, ary.length
70
+ block = ArgHelper.allocate_array_of_type ffi_type, ary.length + 1
61
71
  block.send "put_array_of_#{ffi_type}", 0, ary
72
+ block.send("put_#{ffi_type}",
73
+ ary.length * FFI.type_size(ffi_type),
74
+ (ffi_type == :pointer ? nil : 0))
62
75
 
63
76
  self.new block
64
77
  end
@@ -0,0 +1,27 @@
1
+ module GirFFI
2
+ module InfoExt
3
+ # Extensions for GObjectIntrospection::IArgInfo needed by GirFFI
4
+ module IArgInfo
5
+ def cast_signal_argument arg
6
+ arg_t = self.argument_type
7
+ if arg_t.tag == :interface
8
+ iface = arg_t.interface
9
+ kls = GirFFI::Builder.build_class iface
10
+ case iface.info_type
11
+ when :enum, :flags
12
+ kls[arg]
13
+ when :interface
14
+ arg.to_object
15
+ else
16
+ kls.wrap(arg)
17
+ end
18
+ else
19
+ arg
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ GObjectIntrospection::IArgInfo.send :include, GirFFI::InfoExt::IArgInfo
27
+
@@ -1,5 +1,6 @@
1
1
  module GirFFI
2
2
  module InfoExt
3
+ # Extensions for GObjectIntrospection::IFieldInfo needed by GirFFI
3
4
  module IFieldInfo
4
5
  def layout_specification
5
6
  [ name.to_sym,
@@ -1,5 +1,6 @@
1
1
  module GirFFI
2
2
  module InfoExt
3
+ # Extensions for GObjectIntrospection::IPropertyInfo needed by GirFFI
3
4
  module IPropertyInfo
4
5
  def getter_name
5
6
  name.gsub(/-/, '_')
@@ -4,7 +4,7 @@ module GirFFI
4
4
  module InfoExt
5
5
  module IRegisteredTypeInfo
6
6
  def full_type_name
7
- "::#{safe_namespace}::#{name}"
7
+ "::#{safe_namespace}::#{name}"
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,65 @@
1
+ module GirFFI
2
+ module InfoExt
3
+ # Extensions for GObjectIntrospection::ISignalInfo needed by GirFFI
4
+ module ISignalInfo
5
+ # Create a signal hander callback. Wraps the given block in such a way that
6
+ # arguments and return value are cast correctly to the ruby world and back.
7
+ #
8
+ # @param block The body of the signal handler
9
+ #
10
+ # @return [FFI::Function] The signal handler, ready to be passed as a
11
+ # callback to C.
12
+ def signal_callback &block
13
+ GirFFI::Builder.build_callback self, &signal_callback_args(&block)
14
+ end
15
+
16
+ # TODO: Generate cast back methods using existing Argument builders.
17
+ def cast_back_signal_arguments *arguments
18
+ instance = GirFFI::ArgHelper.object_pointer_to_object arguments.shift
19
+ user_data = GirFFI::ArgHelper::OBJECT_STORE[arguments.pop.address]
20
+
21
+ extra_arguments = self.args.zip(arguments).map do |info, arg|
22
+ info.cast_signal_argument(arg)
23
+ end
24
+
25
+ return [instance, *extra_arguments].push user_data
26
+ end
27
+
28
+ def signal_callback_args &block
29
+ raise ArgumentError, "Block needed" unless block
30
+ return Proc.new do |*args|
31
+ mapped = cast_back_signal_arguments(*args)
32
+ block.call(*mapped)
33
+ end
34
+ end
35
+
36
+ def signal_arguments_to_gvalue_array instance, *rest
37
+ arr = ::GObject::ValueArray.new self.n_args + 1
38
+
39
+ arr.append signal_reciever_to_gvalue instance
40
+
41
+ self.args.zip(rest).each do |info, arg|
42
+ arr.append info.argument_type.make_g_value.set_value(arg)
43
+ end
44
+
45
+ arr
46
+ end
47
+
48
+ def gvalue_for_signal_return_value
49
+ GObject::Value.for_g_type return_type.g_type
50
+ end
51
+
52
+ private
53
+
54
+ def signal_reciever_to_gvalue instance
55
+ val = ::GObject::Value.new
56
+ val.init ::GObject.type_from_instance instance
57
+ val.set_instance instance
58
+ return val
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+
65
+ GObjectIntrospection::ISignalInfo.send :include, GirFFI::InfoExt::ISignalInfo
@@ -2,9 +2,24 @@ require 'gir_ffi/builder_helper'
2
2
 
3
3
  module GirFFI
4
4
  module InfoExt
5
+ # Extensions for GObjectIntrospection::IArgInfo needed by GirFFI
5
6
  module ITypeInfo
6
7
  include BuilderHelper
7
8
 
9
+ def g_type
10
+ tag = self.tag
11
+ case tag
12
+ when :interface
13
+ interface.g_type
14
+ else
15
+ GObject::TYPE_TAG_TO_GTYPE[tag]
16
+ end
17
+ end
18
+
19
+ def make_g_value
20
+ GObject::Value.for_g_type g_type
21
+ end
22
+
8
23
  def layout_specification_type
9
24
  ffitype = GirFFI::Builder.itypeinfo_to_ffitype self
10
25
  case ffitype
@@ -1,5 +1,6 @@
1
1
  module GirFFI
2
2
  module InfoExt
3
+ # Extension module provinding a #safe_name method suitable for types.
3
4
  module SafeConstantName
4
5
  def safe_name
5
6
  name.gsub(/^./) do |char|
@@ -1,5 +1,6 @@
1
1
  module GirFFI
2
2
  module InfoExt
3
+ # Extension module provinding a #safe_name method suitable for functions.
3
4
  module SafeFunctionName
4
5
  def safe_name
5
6
  name = self.name
@@ -1,6 +1,8 @@
1
1
  require 'gir_ffi/info_ext/safe_constant_name'
2
2
  require 'gir_ffi/info_ext/safe_function_name'
3
+ require 'gir_ffi/info_ext/i_arg_info'
3
4
  require 'gir_ffi/info_ext/i_field_info'
4
5
  require 'gir_ffi/info_ext/i_property_info'
6
+ require 'gir_ffi/info_ext/i_signal_info'
5
7
  require 'gir_ffi/info_ext/i_registered_type_info'
6
8
  require 'gir_ffi/info_ext/i_type_info'