gir_ffi 0.5.1 → 0.5.2

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 (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'