gir_ffi 0.6.3 → 0.6.4

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 (67) hide show
  1. data/History.txt +11 -0
  2. data/README.md +24 -6
  3. data/lib/ffi-glib/ptr_array.rb +17 -1
  4. data/lib/ffi-glib/variant.rb +15 -0
  5. data/lib/ffi-glib.rb +1 -0
  6. data/lib/ffi-gobject/object.rb +1 -1
  7. data/lib/ffi-gobject/ruby_closure.rb +1 -1
  8. data/lib/ffi-gobject/value.rb +13 -3
  9. data/lib/ffi-gobject.rb +1 -2
  10. data/lib/ffi-gobject_introspection/i_enum_info.rb +14 -0
  11. data/lib/ffi-gobject_introspection/lib.rb +2 -0
  12. data/lib/gir_ffi/arg_helper.rb +2 -0
  13. data/lib/gir_ffi/argument_builder.rb +22 -21
  14. data/lib/gir_ffi/base_argument_builder.rb +2 -1
  15. data/lib/gir_ffi/builder/module.rb +2 -3
  16. data/lib/gir_ffi/builder/type/enum.rb +18 -1
  17. data/lib/gir_ffi/builder/type/object.rb +20 -18
  18. data/lib/gir_ffi/class_base.rb +0 -1
  19. data/lib/gir_ffi/enum_base.rb +25 -0
  20. data/lib/gir_ffi/ffi_ext.rb +1 -0
  21. data/lib/gir_ffi/function_builder.rb +50 -33
  22. data/lib/gir_ffi/in_out_pointer.rb +0 -5
  23. data/lib/gir_ffi/in_pointer.rb +7 -5
  24. data/lib/gir_ffi/info_ext/i_callable_info.rb +4 -0
  25. data/lib/gir_ffi/info_ext/i_enum_info.rb +13 -0
  26. data/lib/gir_ffi/info_ext/i_field_info.rb +1 -1
  27. data/lib/gir_ffi/info_ext/i_object_info.rb +11 -0
  28. data/lib/gir_ffi/info_ext/i_registered_type_info.rb +11 -0
  29. data/lib/gir_ffi/info_ext/i_struct_info.rb +11 -0
  30. data/lib/gir_ffi/info_ext/i_type_info.rb +10 -19
  31. data/lib/gir_ffi/info_ext/i_union_info.rb +12 -0
  32. data/lib/gir_ffi/info_ext/safe_constant_name.rb +0 -2
  33. data/lib/gir_ffi/info_ext.rb +4 -0
  34. data/lib/gir_ffi/interface_base.rb +0 -1
  35. data/lib/gir_ffi/return_value_builder.rb +3 -2
  36. data/lib/gir_ffi/type_map.rb +3 -0
  37. data/lib/gir_ffi/version.rb +1 -1
  38. data/lib/gir_ffi/zero_terminated.rb +36 -3
  39. data/lib/gir_ffi-base/gir_ffi/library.rb +17 -0
  40. data/lib/gir_ffi-base/gobject/lib.rb +2 -2
  41. data/lib/gir_ffi.rb +1 -0
  42. data/tasks/test.rake +1 -0
  43. data/test/base_test_helper.rb +22 -2
  44. data/test/ffi-glib/ruby_closure_test.rb +1 -1
  45. data/test/ffi-glib/variant_test.rb +10 -0
  46. data/test/ffi-gobject/value_test.rb +24 -8
  47. data/test/ffi-gobject_introspection/i_enum_info_test.rb +17 -0
  48. data/test/gir_ffi/argument_builder_test.rb +66 -24
  49. data/test/gir_ffi/builder_test.rb +1 -1
  50. data/test/gir_ffi/function_builder_test.rb +1 -3
  51. data/test/gir_ffi/in_out_pointer_test.rb +5 -3
  52. data/test/gir_ffi/in_pointer_test.rb +32 -2
  53. data/test/gir_ffi/info_ext/i_arg_info_test.rb +2 -2
  54. data/test/gir_ffi/info_ext/i_callable_info_test.rb +2 -2
  55. data/test/gir_ffi/info_ext/i_field_info_test.rb +14 -20
  56. data/test/gir_ffi/info_ext/i_function_info_test.rb +2 -2
  57. data/test/gir_ffi/info_ext/i_signal_info_test.rb +2 -2
  58. data/test/gir_ffi/info_ext/i_type_info_test.rb +8 -8
  59. data/test/gir_ffi/info_ext/safe_constant_name_test.rb +2 -2
  60. data/test/gir_ffi/info_ext/safe_function_name_test.rb +2 -2
  61. data/test/gir_ffi/return_value_builder_test.rb +18 -1
  62. data/test/gir_ffi/zero_terminated_test.rb +10 -0
  63. data/test/gir_ffi_test_helper.rb +0 -19
  64. data/test/integration/generated_gimarshallingtests_test.rb +291 -99
  65. data/test/integration/generated_regress_test.rb +138 -14
  66. data/test/lib/autogen.sh +6 -2
  67. metadata +14 -2
data/History.txt CHANGED
@@ -1,3 +1,14 @@
1
+ == 0.6.4 / 2013-06-30
2
+
3
+ * Represent enum types by modules wrapping FFI::Enum
4
+ * Support functions on enums
5
+ * Handle zero-terminated arrays of types other than int32
6
+ * Add override for GLib::Variant#get_string
7
+ * Handle non-throwing arguments and return values of type GError
8
+ * Handle arguments and return values of type GPtrArray
9
+ * Handle caller-allocated arguments of type GArray
10
+ * Deprecate GObject::Value#ruby_value, replacing it with #get_value
11
+
1
12
  == 0.6.3 / 2013-06-15
2
13
 
3
14
  * Make use of enums as element type for GHashTable and other containers
data/README.md CHANGED
@@ -20,12 +20,18 @@ Ruby bindings for GNOME using the GObject Introspection Repository.
20
20
 
21
21
  require 'gir_ffi'
22
22
 
23
- GirFFI.setup :TheNamespace
23
+ # Set up the namespace you wish to use
24
+ GirFFI.setup :Gio
24
25
 
25
- TheNamespace.some_function
26
+ # Create an object
27
+ inet_address = Gio::InetAddress.new_from_string "127.0.0.1"
26
28
 
27
- obj = TheNamespace::SomeClass.new
28
- obj.some_method with, some, args
29
+ # Call some methods on the object
30
+ inet_address.is_loopback # => true
31
+ inet_address.is_multicast # => false
32
+
33
+ # Call a function in the namespace
34
+ Gio.dbus_is_name "foo" # => false
29
35
 
30
36
  ## Install
31
37
 
@@ -33,8 +39,8 @@ Ruby bindings for GNOME using the GObject Introspection Repository.
33
39
 
34
40
  ## Requirements
35
41
 
36
- GirFFI should work on MRI 1.8 and 1.9, and JRuby in both 1.8 and 1.9
37
- modes. It does not work on Rubinius yet.
42
+ GirFFI should work on MRI 1.8, 1.9 and 2.0, JRuby in both 1.8 and 1.9
43
+ modes, and on Rubinius in both 1.8 and 1.9 modes.
38
44
 
39
45
  You will also need gobject-introspection installed with some
40
46
  introspection data.
@@ -53,6 +59,18 @@ On Debian and Ubuntu, installing `libgirepository1.0-dev` and
53
59
 
54
60
  GirFFI has not been tested on Mac OS X or Microsoft Windows. YMMV.
55
61
 
62
+ ## Overrides
63
+
64
+ Sometimes, the GIR data is incorrect, or not detailed enough, and a
65
+ reasonable binding cannot be created automatically. For these cases,
66
+ overrides can be defined. The following gems with overrides
67
+ already exist:
68
+
69
+ * `gir_ffi-gtk`: overrides for Gtk+ 2 and 3.
70
+ * `gir_ffi-cairo`: overrides for Cairo
71
+ * `gir_ffi-pango`: overrides for Pango
72
+ * `gir_ffi-tracker`: overrides for Tracker
73
+
56
74
  ## Hacking and contributing
57
75
 
58
76
  If you want to help out, have a look at TODO.rdoc, and check the notes
@@ -15,10 +15,22 @@ module GLib
15
15
  end
16
16
 
17
17
  def self.new type
18
- wrap(Lib.g_ptr_array_new).tap {|it|
18
+ wrap(type, Lib.g_ptr_array_new)
19
+ end
20
+
21
+ def self.wrap type, ptr
22
+ super(ptr).tap {|it|
19
23
  it.element_type = type}
20
24
  end
21
25
 
26
+ def self.from type, it
27
+ case it
28
+ when self then it
29
+ when FFI::Pointer then wrap type, it
30
+ else self.new(type).tap {|arr| arr.add_array it}
31
+ end
32
+ end
33
+
22
34
  def self.add array, data
23
35
  array.add data
24
36
  end
@@ -28,6 +40,10 @@ module GLib
28
40
  Lib.g_ptr_array_add self, ptr
29
41
  end
30
42
 
43
+ def add_array ary
44
+ ary.each {|item| add item}
45
+ end
46
+
31
47
  # Re-implementation of the g_ptr_array_index macro
32
48
  def index idx
33
49
  sz = FFI.type_size :pointer
@@ -0,0 +1,15 @@
1
+ module GLib
2
+ load_class :Variant
3
+
4
+ # Overrides for GVariant, GLib's variant data type.
5
+ class Variant
6
+ setup_instance_method "get_string"
7
+
8
+ def get_string_with_override
9
+ get_string_without_override.first
10
+ end
11
+
12
+ alias get_string_without_override get_string
13
+ alias get_string get_string_with_override
14
+ end
15
+ end
data/lib/ffi-glib.rb CHANGED
@@ -11,6 +11,7 @@ require 'ffi-glib/ptr_array'
11
11
  require 'ffi-glib/s_list'
12
12
  require 'ffi-glib/sized_array'
13
13
  require 'ffi-glib/strv'
14
+ require 'ffi-glib/variant'
14
15
 
15
16
  module GLib
16
17
  load_class :HFunc
@@ -18,7 +18,7 @@ module GObject
18
18
 
19
19
  get_property_without_override property_name, gvalue
20
20
 
21
- adjust_value_to_type gvalue.ruby_value, type
21
+ adjust_value_to_type gvalue.get_value, type
22
22
  end
23
23
 
24
24
  def set_property_with_override property_name, value
@@ -43,7 +43,7 @@ module GObject
43
43
  rclosure = wrap(closure.to_ptr)
44
44
 
45
45
  args = n_param_values.times.map {|idx|
46
- Value.wrap(param_values.to_ptr + idx * Value::Struct.size).ruby_value
46
+ Value.wrap(param_values.to_ptr + idx * Value::Struct.size).get_value
47
47
  }
48
48
 
49
49
  result = rclosure.invoke_block(*args)
@@ -15,6 +15,7 @@ module GObject
15
15
  TYPE_TO_SET_METHOD_MAP = {
16
16
  TYPE_BOOLEAN => :set_boolean,
17
17
  TYPE_INT => :set_int,
18
+ TYPE_INT64 => :set_int64,
18
19
  TYPE_STRING => :set_string,
19
20
  TYPE_FLOAT => :set_float,
20
21
  TYPE_DOUBLE => :set_double,
@@ -25,6 +26,10 @@ module GObject
25
26
  TYPE_ENUM => :set_enum
26
27
  }
27
28
 
29
+ def value= val
30
+ set_value val
31
+ end
32
+
28
33
  def set_value val
29
34
  send set_method, val
30
35
  self
@@ -62,6 +67,7 @@ module GObject
62
67
  TYPE_TO_GET_METHOD_MAP = {
63
68
  TYPE_BOOLEAN => :get_boolean,
64
69
  TYPE_INT => :get_int,
70
+ TYPE_INT64 => :get_int64,
65
71
  TYPE_STRING => :get_string,
66
72
  TYPE_FLOAT => :get_float,
67
73
  TYPE_DOUBLE => :get_double,
@@ -70,11 +76,15 @@ module GObject
70
76
  TYPE_POINTER => :get_pointer
71
77
  }
72
78
 
73
- # TODO: Rename to get_value
74
- def ruby_value
79
+ def get_value
75
80
  send get_method
76
81
  end
77
82
 
83
+ # @deprecated Compatibility function. Remove in 0.7.0.
84
+ def ruby_value
85
+ get_value
86
+ end
87
+
78
88
  class << self
79
89
  # TODO: Give more generic name
80
90
  def wrap_ruby_value val
@@ -94,7 +104,7 @@ module GObject
94
104
 
95
105
  def for_g_type g_type
96
106
  return nil if g_type == TYPE_NONE
97
- self.new.tap {|it| it.init g_type }
107
+ self.new.init g_type
98
108
  end
99
109
  end
100
110
 
data/lib/ffi-gobject.rb CHANGED
@@ -109,8 +109,7 @@ module GObject
109
109
  attach_function :g_hash_table_get_type, [], :size_t
110
110
 
111
111
  attach_function :g_signal_connect_data,
112
- [:pointer, :string, Callback, :pointer, ClosureNotify,
113
- ConnectFlags],
112
+ [:pointer, :string, Callback, :pointer, ClosureNotify, ConnectFlags],
114
113
  :ulong
115
114
  attach_function :g_closure_set_marshal,
116
115
  [:pointer, ClosureMarshal], :void
@@ -11,6 +11,20 @@ module GObjectIntrospection
11
11
  ##
12
12
  build_array_method :values
13
13
 
14
+ def get_n_methods
15
+ Lib.g_enum_info_get_n_methods @gobj
16
+ end
17
+ def get_method(index)
18
+ IFunctionInfo.wrap(Lib.g_enum_info_get_method @gobj, index)
19
+ end
20
+
21
+ ##
22
+ build_array_method :get_methods
23
+
24
+ def find_method name
25
+ get_methods.find {|m| m.name == name}
26
+ end
27
+
14
28
  def storage_type
15
29
  Lib.g_enum_info_get_storage_type @gobj
16
30
  end
@@ -178,6 +178,8 @@ module GObjectIntrospection
178
178
  attach_function :g_enum_info_get_storage_type, [:pointer], :ITypeTag
179
179
  attach_function :g_enum_info_get_n_values, [:pointer], :int
180
180
  attach_function :g_enum_info_get_value, [:pointer, :int], :pointer
181
+ attach_function :g_enum_info_get_n_methods, [:pointer], :int
182
+ attach_function :g_enum_info_get_method, [:pointer, :int], :pointer
181
183
 
182
184
  # IObjectInfo
183
185
  attach_function :g_object_info_get_type_name, [:pointer], :string
@@ -29,6 +29,8 @@ module GirFFI
29
29
  case type
30
30
  when Class
31
31
  ptr_to_interface_array type, ptr, size
32
+ when Module
33
+ ptr_to_enum_array type, ptr, size
32
34
  when Array
33
35
  ptr_to_interface_pointer_array type[1], ptr, size
34
36
  when FFI::Enum
@@ -53,8 +53,6 @@ module GirFFI
53
53
  else
54
54
  "#{argument_class_name}.wrap(#{output_conversion_arguments})"
55
55
  end
56
- elsif is_fixed_length_array?
57
- "GLib::SizedArray.wrap(#{subtype_tag_or_class_name}, #{array_size}, #{callarg}.to_value)"
58
56
  else
59
57
  "#{callarg}.to_value"
60
58
  end
@@ -68,10 +66,6 @@ module GirFFI
68
66
  specialized_type_tag == :c && type_info.array_fixed_size > -1
69
67
  end
70
68
 
71
- def is_fixed_length_array?
72
- specialized_type_tag == :c
73
- end
74
-
75
69
  def fixed_array_size_check
76
70
  size = type_info.array_fixed_size
77
71
  "GirFFI::ArgHelper.check_fixed_array_size #{size}, #{@name}, \"#{@name}\""
@@ -93,7 +87,11 @@ module GirFFI
93
87
  def set_function_call_argument
94
88
  value = if @direction == :out
95
89
  if is_caller_allocated_object?
96
- "#{argument_class_name}._allocate"
90
+ if specialized_type_tag == :array
91
+ "#{argument_class_name}.new #{elm_t}"
92
+ else
93
+ "#{argument_class_name}.new"
94
+ end
97
95
  else
98
96
  "GirFFI::InOutPointer.for #{specialized_type_tag.inspect}"
99
97
  end
@@ -108,42 +106,45 @@ module GirFFI
108
106
  end
109
107
 
110
108
  def is_caller_allocated_object?
111
- [:object, :struct].include?(specialized_type_tag) &&
109
+ [ :struct, :array ].include?(specialized_type_tag) &&
112
110
  @arginfo.caller_allocates?
113
111
  end
114
112
 
115
113
  def needs_outgoing_parameter_conversion?
116
- [ :array, :enum, :flags, :ghash, :glist, :gslist, :object, :struct,
117
- :strv, :utf8 ].include?(specialized_type_tag)
114
+ [ :array, :c, :enum, :error, :flags, :ghash, :glist, :gslist, :object,
115
+ :ptr_array, :struct, :strv, :utf8 ].include?(specialized_type_tag)
118
116
  end
119
117
 
120
118
  def needs_ingoing_parameter_conversion?
121
119
  @direction == :inout ||
122
- [ :object, :struct, :callback, :utf8, :void, :glist, :gslist, :ghash,
123
- :array, :c, :zero_terminated, :strv ].include?(specialized_type_tag)
120
+ [ :array, :c, :callback, :ghash, :glist, :gslist, :object, :ptr_array,
121
+ :struct, :strv, :utf8, :void, :zero_terminated ].include?(specialized_type_tag)
124
122
  end
125
123
 
126
124
  def ingoing_parameter_conversion
127
125
  case specialized_type_tag
128
126
  when :enum, :flags
129
127
  base = "#{argument_class_name}[#{parameter_conversion_arguments}]"
130
- "GirFFI::InOutPointer.from #{specialized_type_tag.inspect}, #{base}"
131
- when :object, :struct, :void, :glist, :gslist, :ghash, :array,
132
- :zero_terminated, :strv, :callback, :utf8, :c
128
+ when :array, :c, :callback, :ghash, :glist, :gslist, :object, :ptr_array,
129
+ :struct, :strv, :utf8, :void, :zero_terminated
133
130
  base = "#{argument_class_name}.from(#{parameter_conversion_arguments})"
134
- if has_output_value?
135
- "GirFFI::InOutPointer.from :pointer, #{base}"
136
- else
137
- base
138
- end
139
131
  else
140
132
  base = "#{parameter_conversion_arguments}"
133
+ end
134
+
135
+ if has_output_value?
141
136
  "GirFFI::InOutPointer.from #{specialized_type_tag.inspect}, #{base}"
137
+ else
138
+ base
142
139
  end
143
140
  end
144
141
 
145
142
  def output_conversion_arguments
146
- conversion_arguments "#{callarg}.to_value"
143
+ if specialized_type_tag == :c
144
+ "#{subtype_tag_or_class_name}, #{array_size}, #{callarg}.to_value"
145
+ else
146
+ conversion_arguments "#{callarg}.to_value"
147
+ end
147
148
  end
148
149
 
149
150
  def parameter_conversion_arguments
@@ -42,6 +42,7 @@ module GirFFI
42
42
  :byte_array => 'GLib::ByteArray',
43
43
  :c => 'GLib::SizedArray',
44
44
  :callback => 'GirFFI::Callback',
45
+ :error => 'GLib::Error',
45
46
  :ghash => 'GLib::HashTable',
46
47
  :glist => 'GLib::List',
47
48
  :gslist => 'GLib::SList',
@@ -118,7 +119,7 @@ module GirFFI
118
119
  "#{specialized_type_tag.inspect}, #{name}"
119
120
  when :c
120
121
  "#{subtype_tag_or_class_name}, #{type_info.array_fixed_size}, #{name}"
121
- when :glist, :gslist, :ghash, :array, :zero_terminated
122
+ when :array, :ghash, :glist, :gslist, :ptr_array, :zero_terminated
122
123
  "#{elm_t}, #{name}"
123
124
  when :callback
124
125
  iface = type_info.interface
@@ -80,8 +80,8 @@ module GirFFI
80
80
  def setup_lib_for_ffi
81
81
  @lib = get_or_define_module @module, :Lib
82
82
 
83
- unless (class << @lib; self.include? FFI::Library; end)
84
- @lib.extend FFI::Library
83
+ unless (class << @lib; self.include? GirFFI::Library; end)
84
+ @lib.extend GirFFI::Library
85
85
  @lib.ffi_lib_flags :global, :lazy
86
86
  libspec = gir.shared_library(@namespace)
87
87
  unless libspec.nil?
@@ -123,6 +123,5 @@ module GirFFI
123
123
  def get_or_define_module parent, name
124
124
  optionally_define_constant(parent, name) { Module.new }
125
125
  end
126
-
127
126
  end
128
127
  end
@@ -1,4 +1,6 @@
1
1
  require 'gir_ffi/builder/type/registered_type'
2
+ require 'gir_ffi/builder/type/with_methods'
3
+ require 'gir_ffi/enum_base'
2
4
 
3
5
  module GirFFI
4
6
  module Builder
@@ -8,6 +10,8 @@ module GirFFI
8
10
  # attached to the appropriate namespace module, and will be defined
9
11
  # as an enum for FFI.
10
12
  class Enum < RegisteredType
13
+ include WithMethods
14
+
11
15
  private
12
16
 
13
17
  def enum_sym
@@ -22,11 +26,15 @@ module GirFFI
22
26
  end
23
27
 
24
28
  def instantiate_class
25
- @klass = optionally_define_constant namespace_module, @classname do
29
+ @klass = get_or_define_module namespace_module, @classname
30
+ @enum = optionally_define_constant @klass, :Enum do
26
31
  lib.enum(enum_sym, value_spec)
27
32
  end
28
33
  unless already_set_up
34
+ @klass.extend superclass
35
+ setup_constants
29
36
  setup_gtype_getter
37
+ stub_methods
30
38
  setup_inspect
31
39
  end
32
40
  end
@@ -42,6 +50,15 @@ module GirFFI
42
50
  def already_set_up
43
51
  @klass.respond_to? :get_gtype
44
52
  end
53
+
54
+ def superclass
55
+ @superclass ||= EnumBase
56
+ end
57
+
58
+ # FIXME: Remove duplication with Builder::Module
59
+ def get_or_define_module parent, name
60
+ optionally_define_constant(parent, name) { ::Module.new }
61
+ end
45
62
  end
46
63
  end
47
64
  end
@@ -51,7 +51,7 @@ module GirFFI
51
51
  setup_interfaces
52
52
  end
53
53
 
54
- # FIXME: Private method only in subclass
54
+ # FIXME: Private method only used in subclass
55
55
  def layout_superclass
56
56
  FFI::Struct
57
57
  end
@@ -69,16 +69,14 @@ module GirFFI
69
69
  end
70
70
 
71
71
  def superclass
72
- unless defined? @superclass
73
- if parent
74
- @superclass = Builder.build_class parent
75
- else
76
- @superclass = ObjectBase
77
- end
78
- end
79
- @superclass
72
+ @superclass ||= if parent
73
+ Builder.build_class parent
74
+ else
75
+ ObjectBase
76
+ end
80
77
  end
81
78
 
79
+ # TODO: Unify with field accessor setup.
82
80
  def setup_property_accessors
83
81
  info.properties.each do |prop|
84
82
  setup_accessors_for_property_info prop
@@ -94,20 +92,24 @@ module GirFFI
94
92
  end
95
93
 
96
94
  # TODO: Guard agains accidental invocation of undefined vfuncs.
95
+ # TODO: Create object responsible for creating these invokers
97
96
  def setup_vfunc_invokers
98
97
  info.vfuncs.each do |vfinfo|
99
- invoker = vfinfo.invoker
100
- next if invoker.nil?
101
- next if invoker.name == vfinfo.name
102
-
103
- @klass.class_eval "
104
- def #{vfinfo.name} *args, &block
105
- #{invoker.name}(*args, &block)
106
- end
107
- "
98
+ if (invoker = vfinfo.invoker)
99
+ define_vfunc_invoker vfinfo.name, invoker.name
100
+ end
108
101
  end
109
102
  end
110
103
 
104
+ def define_vfunc_invoker vfunc_name, invoker_name
105
+ return if vfunc_name == invoker_name
106
+ @klass.class_eval "
107
+ def #{vfunc_name} *args, &block
108
+ #{invoker_name}(*args, &block)
109
+ end
110
+ "
111
+ end
112
+
111
113
  def setup_interfaces
112
114
  interfaces.each do |iface|
113
115
  @klass.class_eval do
@@ -1,5 +1,4 @@
1
1
  require 'forwardable'
2
- require 'gir_ffi/ffi_ext/pointer'
3
2
 
4
3
  module GirFFI
5
4
  # Base class for all generated classes. Contains code for dealing with
@@ -0,0 +1,25 @@
1
+ module GirFFI
2
+ module EnumBase
3
+ def [](arg)
4
+ self::Enum[arg]
5
+ end
6
+
7
+ def setup_and_call method, *arguments, &block
8
+ result = setup_method method.to_s
9
+
10
+ unless result
11
+ raise RuntimeError, "Unable to set up method #{method} in #{self}"
12
+ end
13
+
14
+ self.send method, *arguments, &block
15
+ end
16
+
17
+ def gir_ffi_builder
18
+ self.const_get :GIR_FFI_BUILDER
19
+ end
20
+
21
+ def setup_method name
22
+ gir_ffi_builder.setup_method name
23
+ end
24
+ end
25
+ end
@@ -0,0 +1 @@
1
+ require 'gir_ffi/ffi_ext/pointer'
@@ -15,81 +15,98 @@ module GirFFI
15
15
 
16
16
  def generate
17
17
  vargen = GirFFI::VariableNameGenerator.new
18
- @data = @info.args.map {|arg| ArgumentBuilder.new vargen, arg }
19
- @rvdata = ReturnValueBuilder.new(vargen, @info.return_type,
20
- @info.constructor?)
18
+ @argument_builders = @info.args.map {|arg| ArgumentBuilder.new vargen, arg }
19
+ @return_value_builder = ReturnValueBuilder.new(vargen, @info.return_type,
20
+ @info.constructor?)
21
21
 
22
- alldata = @data.dup << @rvdata
22
+ link_array_length_arguments
23
+ setup_error_argument vargen
24
+ return filled_out_template
25
+ end
26
+
27
+ private
28
+
29
+ def link_array_length_arguments
30
+ alldata = @argument_builders.dup << @return_value_builder
23
31
 
24
32
  alldata.each {|data|
25
33
  idx = data.type_info.array_length
26
34
  if idx > -1
27
- data.length_arg = @data[idx]
28
- @data[idx].array_arg = data
35
+ other_data = @argument_builders[idx]
36
+ data.length_arg = other_data
37
+ other_data.array_arg = data
29
38
  end
30
39
  }
31
-
32
- setup_error_argument vargen
33
- return filled_out_template
34
40
  end
35
41
 
36
- private
37
-
38
42
  def setup_error_argument vargen
39
43
  klass = @info.throws? ? ErrorArgumentBuilder : NullArgumentBuilder
40
44
  @errarg = klass.new vargen, nil, nil, :error
41
45
  end
42
46
 
43
47
  def filled_out_template
44
- lines = pre
45
- lines << "#{capture}#{@libmodule}.#{@info.symbol} #{callargs.join(', ')}"
46
- lines << post
47
-
48
48
  meta = @info.method? ? '' : "self."
49
49
 
50
- code = "def #{meta}#{@info.safe_name} #{inargs.join(', ')}\n"
51
- code << lines.join("\n").indent
50
+ code = "def #{meta}#{@info.safe_name} #{method_arguments.join(', ')}\n"
51
+ code << method_body
52
52
  code << "\nend\n"
53
53
  end
54
54
 
55
- def inargs
56
- @data.map(&:inarg).compact
55
+ def method_body
56
+ lines = preparation << function_call << post_processing << cleanup
57
+ lines << "return #{return_values.join(', ')}" if has_return_values?
58
+ lines.flatten.join("\n").indent
57
59
  end
58
60
 
59
- def callargs
60
- ca = @data.map(&:callarg)
61
+ def function_call
62
+ "#{capture}#{@libmodule}.#{@info.symbol} #{function_call_arguments.join(', ')}"
63
+ end
64
+
65
+ def method_arguments
66
+ @argument_builders.map(&:inarg).compact
67
+ end
68
+
69
+ def function_call_arguments
70
+ ca = @argument_builders.map(&:callarg)
61
71
  ca << @errarg.callarg
62
72
  ca.unshift "self" if @info.method?
63
73
  ca.compact
64
74
  end
65
75
 
66
- def pre
67
- pr = @data.map(&:pre)
76
+ def preparation
77
+ pr = @argument_builders.map(&:pre)
68
78
  pr << @errarg.pre
69
79
  pr.flatten
70
80
  end
71
81
 
72
82
  def capture
73
- if (cv = @rvdata.cvar)
83
+ if (cv = @return_value_builder.cvar)
74
84
  "#{cv} = "
75
85
  else
76
86
  ""
77
87
  end
78
88
  end
79
89
 
80
- def post
81
- args = @data.sort_by {|arg| arg.type_info.array_length}
90
+ def post_processing
91
+ # FIXME: Sorting knows too much about internals of ArgumentBuilder.
92
+ args = @argument_builders.sort_by {|arg| arg.type_info.array_length}
93
+ args << @return_value_builder
94
+ args.unshift @errarg
82
95
 
83
- po = args.map {|arg|arg.post} +
84
- @rvdata.post
85
- po.unshift @errarg.post
96
+ args.map {|arg| arg.post}
97
+ end
86
98
 
87
- po += @data.map {|item| item.cleanup}
99
+ def cleanup
100
+ @argument_builders.map {|item| item.cleanup}
101
+ end
88
102
 
89
- retvals = ([@rvdata.retval] + @data.map(&:retval)).compact
90
- po << "return #{retvals.join(', ')}" unless retvals.empty?
103
+ def return_values
104
+ @return_values ||= ([@return_value_builder.retval] +
105
+ @argument_builders.map(&:retval)).compact
106
+ end
91
107
 
92
- po.flatten
108
+ def has_return_values?
109
+ !return_values.empty?
93
110
  end
94
111
  end
95
112
  end