gir_ffi 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/History.txt +8 -0
  2. data/README.md +1 -1
  3. data/TODO.rdoc +12 -4
  4. data/lib/ffi-glib.rb +0 -5
  5. data/lib/ffi-glib/list.rb +1 -1
  6. data/lib/ffi-glib/s_list.rb +1 -1
  7. data/lib/ffi-gobject.rb +2 -3
  8. data/lib/ffi-gobject/closure.rb +4 -3
  9. data/lib/ffi-gobject_introspection/i_base_info.rb +11 -14
  10. data/lib/ffi-gobject_introspection/i_constant_info.rb +1 -1
  11. data/lib/ffi-gobject_introspection/i_function_info.rb +0 -6
  12. data/lib/ffi-gobject_introspection/lib.rb +8 -2
  13. data/lib/gir_ffi.rb +5 -0
  14. data/lib/gir_ffi/arg_helper.rb +1 -1
  15. data/lib/gir_ffi/argument_builder.rb +161 -0
  16. data/lib/gir_ffi/base_argument_builder.rb +146 -0
  17. data/lib/gir_ffi/builder/field.rb +7 -5
  18. data/lib/gir_ffi/builder/module.rb +3 -14
  19. data/lib/gir_ffi/builder/property.rb +0 -2
  20. data/lib/gir_ffi/builder/type/callback.rb +0 -8
  21. data/lib/gir_ffi/builder/type/constant.rb +0 -4
  22. data/lib/gir_ffi/builder/type/enum.rb +0 -4
  23. data/lib/gir_ffi/builder/type/interface.rb +0 -4
  24. data/lib/gir_ffi/builder/type/object.rb +0 -1
  25. data/lib/gir_ffi/builder/type/struct_based.rb +0 -6
  26. data/lib/gir_ffi/builder/type/union.rb +0 -4
  27. data/lib/gir_ffi/builder/type/with_layout.rb +0 -1
  28. data/lib/gir_ffi/builder/type/with_methods.rb +1 -7
  29. data/lib/gir_ffi/callback.rb +9 -0
  30. data/lib/gir_ffi/callback_helper.rb +8 -1
  31. data/lib/gir_ffi/class_base.rb +6 -26
  32. data/lib/gir_ffi/error_argument_builder.rb +17 -0
  33. data/lib/gir_ffi/{builder/function.rb → function_builder.rb} +14 -11
  34. data/lib/gir_ffi/in_out_pointer.rb +29 -36
  35. data/lib/gir_ffi/in_pointer.rb +1 -1
  36. data/lib/gir_ffi/info_ext.rb +6 -0
  37. data/lib/gir_ffi/info_ext/i_field_info.rb +0 -2
  38. data/lib/gir_ffi/info_ext/i_type_info.rb +29 -10
  39. data/lib/gir_ffi/info_ext/safe_constant_name.rb +21 -0
  40. data/lib/gir_ffi/info_ext/safe_function_name.rb +13 -0
  41. data/lib/gir_ffi/interface_base.rb +1 -11
  42. data/lib/gir_ffi/module_base.rb +0 -10
  43. data/lib/gir_ffi/null_argument_builder.rb +9 -0
  44. data/lib/gir_ffi/return_value_builder.rb +75 -0
  45. data/lib/gir_ffi/setter_argument_info.rb +16 -0
  46. data/lib/gir_ffi/type_map.rb +10 -1
  47. data/lib/gir_ffi/version.rb +1 -1
  48. data/tasks/test.rake +61 -0
  49. data/test/base_test_helper.rb +0 -2
  50. data/test/ffi-gobject/value_test.rb +15 -0
  51. data/test/ffi-gobject_introspection/i_base_info_test.rb +31 -6
  52. data/test/ffi-gobject_introspection/i_function_info_test.rb +0 -17
  53. data/test/ffi-gobject_introspection/lib_test.rb +0 -55
  54. data/test/ffi-gobject_test.rb +2 -1
  55. data/test/gir_ffi/argument_builder_test.rb +414 -0
  56. data/test/gir_ffi/base_argument_builder_test.rb +13 -0
  57. data/test/gir_ffi/builder/module_test.rb +4 -40
  58. data/test/gir_ffi/builder/type/callback_test.rb +0 -27
  59. data/test/gir_ffi/builder/type/constant_test.rb +0 -12
  60. data/test/gir_ffi/builder/type/enum_test.rb +0 -20
  61. data/test/gir_ffi/builder/type/interface_test.rb +0 -11
  62. data/test/gir_ffi/builder/type/object_test.rb +2 -2
  63. data/test/gir_ffi/builder/type/struct_test.rb +0 -39
  64. data/test/gir_ffi/builder/type/unintrospectable_test.rb +1 -1
  65. data/test/gir_ffi/builder/type/union_test.rb +0 -11
  66. data/test/gir_ffi/builder_test.rb +3 -11
  67. data/test/gir_ffi/callback_helper_test.rb +7 -0
  68. data/test/gir_ffi/{builder/function_test.rb → function_builder_test.rb} +16 -28
  69. data/test/gir_ffi/in_out_pointer_test.rb +0 -20
  70. data/test/gir_ffi/info_ext/i_type_info_test.rb +112 -26
  71. data/test/gir_ffi/info_ext/safe_constant_name_test.rb +16 -0
  72. data/test/gir_ffi/info_ext/safe_function_name_test.rb +22 -0
  73. data/test/gir_ffi/return_value_builder_test.rb +355 -0
  74. data/test/integration/generated_gimarshallingtests_test.rb +608 -296
  75. data/test/integration/generated_regress_test.rb +879 -494
  76. metadata +35 -24
  77. data/lib/gir_ffi/builder/argument.rb +0 -569
  78. data/lib/gir_ffi/builder/argument/base.rb +0 -151
  79. data/lib/gir_ffi/builder/argument/in_base.rb +0 -14
  80. data/lib/gir_ffi/builder/argument/in_out_base.rb +0 -18
  81. data/lib/gir_ffi/builder/argument/out_base.rb +0 -15
  82. data/test/gir_ffi/builder/argument/base_test.rb +0 -55
  83. data/test/integration/pretty_print_test.rb +0 -33
data/History.txt CHANGED
@@ -1,3 +1,11 @@
1
+ == 0.5.0 / 2013-01-19
2
+
3
+ * Update ffi dependency
4
+ * Add finalizer to release memory for IBaseInfo and descendents
5
+ * Remove deprecated methods
6
+ * Remove pretty-printing functionality
7
+ * Refactor argument handling
8
+
1
9
  == 0.4.3 / 2012-11-02
2
10
 
3
11
  * Remove gobject-introspection version check
data/README.md CHANGED
@@ -72,7 +72,7 @@ If you want to send pull requests or patches, please:
72
72
 
73
73
  ## License
74
74
 
75
- Copyright © 2009–2012 [Matijs van Zuijlen](http://www.matijs.net)
75
+ Copyright © 2009–2013 [Matijs van Zuijlen](http://www.matijs.net)
76
76
 
77
77
  GirFFI is free software, distributed under the terms of the GNU Lesser
78
78
  General Public License, version 2.1 or later. See the file COPYING.LIB for
data/TODO.rdoc CHANGED
@@ -1,10 +1,18 @@
1
1
  = TODO
2
2
 
3
- == Fix helper method names
3
+ == Memory managment
4
4
 
5
- GirFFI adds some methods to all generated modules. For some of these, it
6
- avoids name clashes by prefixing an underscore. This is ugly and must be
7
- changed.
5
+ GirFFI does not attempt to free any memory at the moment, or lower the
6
+ reference count of any objects it gets from GObject. This task therefore involves two parts:
7
+
8
+ - Free non-GObject pointers as needed (at garbage-collection time)
9
+ - Lower reference count of GObjects (at garbage-collection time)
10
+
11
+ == Persistent Ruby GObject identity
12
+
13
+ GirFFI should make sure that if it gets a pointer to a GObject for which a Ruby
14
+ object already exists, the existing object is returned. This involves the use
15
+ of WeakRef, no doubt.
8
16
 
9
17
  == Remove code for passing generic pointers
10
18
 
data/lib/ffi-glib.rb CHANGED
@@ -12,11 +12,6 @@ require 'ffi-glib/ptr_array'
12
12
  require 'ffi-glib/strv'
13
13
 
14
14
  module GLib
15
- # @deprecated Compatibility function. Remove in version 0.5.0.
16
- def self.main_loop_new context, is_running
17
- GLib::MainLoop.new context, is_running
18
- end
19
-
20
15
  load_class :HFunc
21
16
  load_class :HashFunc
22
17
  load_class :EqualFunc
data/lib/ffi-glib/list.rb CHANGED
@@ -13,7 +13,7 @@ module GLib
13
13
 
14
14
  def self.new type
15
15
  _real_new.tap do |it|
16
- struct = ffi_structure.new(FFI::Pointer.new(0))
16
+ struct = self::Struct.new(FFI::Pointer.new(0))
17
17
  it.instance_variable_set :@struct, struct
18
18
  it.element_type = type
19
19
  end
@@ -13,7 +13,7 @@ module GLib
13
13
 
14
14
  def self.new type
15
15
  _real_new.tap do |it|
16
- struct = ffi_structure.new(FFI::Pointer.new(0))
16
+ struct = self::Struct.new(FFI::Pointer.new(0))
17
17
  it.instance_variable_set :@struct, struct
18
18
  it.element_type = type
19
19
  end
data/lib/ffi-gobject.rb CHANGED
@@ -54,7 +54,7 @@ module GObject
54
54
  ObjectClass.wrap klsptr
55
55
  end
56
56
 
57
- _setup_method :signal_emitv
57
+ setup_method :signal_emitv
58
58
 
59
59
  def self.signal_lookup_from_instance signal, object
60
60
  signal_lookup signal, type_from_instance(object)
@@ -72,10 +72,9 @@ module GObject
72
72
 
73
73
  def self.signal_connect object, signal, data=nil, &block
74
74
  callback = Helper.signal_callback object.class, signal, &block
75
+ GirFFI::CallbackHelper.store_callback callback
75
76
  data_ptr = GirFFI::ArgHelper.object_to_inptr data
76
77
 
77
- Lib::CALLBACKS << callback
78
-
79
78
  Lib.g_signal_connect_data object, signal, callback, data_ptr, nil, 0
80
79
  end
81
80
 
@@ -4,9 +4,10 @@ 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(
8
- "GObject", "ClosureMarshal", marshal)
9
- Lib::CALLBACKS << callback
7
+ callback = GirFFI::CallbackHelper.wrap_in_callback_args_mapper("GObject",
8
+ "ClosureMarshal",
9
+ marshal)
10
+ GirFFI::CallbackHelper.store_callback callback
10
11
  Lib.g_closure_set_marshal self, callback
11
12
  end
12
13
  end
@@ -2,8 +2,18 @@ module GObjectIntrospection
2
2
  # Wraps GIBaseInfo struct, the base \type for all info types.
3
3
  # Decendant types will be implemented as needed.
4
4
  class IBaseInfo
5
- def initialize ptr
5
+ def initialize ptr, lib=Lib
6
+ raise ArgumentError, "ptr must not be nil" if ptr.nil?
7
+ raise ArgumentError, "ptr must not be null" if ptr.null?
8
+
9
+ ObjectSpace.define_finalizer self, self.class.make_finalizer(lib, ptr)
10
+
6
11
  @gobj = ptr
12
+ @lib = lib
13
+ end
14
+
15
+ def self.make_finalizer lib, ptr
16
+ proc { lib.g_base_info_unref ptr }
7
17
  end
8
18
 
9
19
  def to_ptr
@@ -31,23 +41,10 @@ module GObjectIntrospection
31
41
  CODE
32
42
  end
33
43
 
34
- private_class_method :new
35
-
36
44
  def name
37
45
  Lib.g_base_info_get_name @gobj
38
46
  end
39
47
 
40
- def safe_name
41
- name.gsub(/^./) do |char|
42
- case char
43
- when "_"
44
- "Private___"
45
- else
46
- char.upcase
47
- end
48
- end
49
- end
50
-
51
48
  def info_type
52
49
  Lib.g_base_info_get_type @gobj
53
50
  end
@@ -1,5 +1,5 @@
1
1
  module GObjectIntrospection
2
- # Wraps a GIConstantInfo struct; represents an constant.
2
+ # Wraps a GIConstantInfo struct; represents a constant.
3
3
  class IConstantInfo < IBaseInfo
4
4
  TYPE_TAG_TO_UNION_MEMBER = {
5
5
  :gint8 => :v_int8,
@@ -28,11 +28,5 @@ module GObjectIntrospection
28
28
  def throws?
29
29
  flags & 32 != 0
30
30
  end
31
-
32
- def safe_name
33
- name = self.name
34
- return "_" if name.empty?
35
- name
36
- end
37
31
  end
38
32
  end
@@ -49,6 +49,7 @@ module GObjectIntrospection
49
49
  :unresolved
50
50
  ]
51
51
 
52
+ attach_function :g_base_info_unref, [:pointer], :void
52
53
  attach_function :g_base_info_get_type, [:pointer], :IInfoType
53
54
  attach_function :g_base_info_get_name, [:pointer], :string
54
55
  attach_function :g_base_info_get_namespace, [:pointer], :string
@@ -104,8 +105,13 @@ module GObjectIntrospection
104
105
  # retrieve the correct values before declaring the ITypeTag enum.
105
106
  attach_function :tmp_type_tag_to_string, :g_type_tag_to_string, [:int], :string
106
107
  type_tag_map = (0..31).map { |id|
107
- [tmp_type_tag_to_string(id).to_sym, id]
108
- }.flatten
108
+ sym = tmp_type_tag_to_string(id).to_sym
109
+ if sym == :unknown
110
+ nil
111
+ else
112
+ [sym, id]
113
+ end
114
+ }.compact.flatten
109
115
  enum :ITypeTag, type_tag_map
110
116
 
111
117
  # Now, attach g_type_tag_to_string again under its own name with an
data/lib/gir_ffi.rb CHANGED
@@ -4,8 +4,13 @@ require 'gir_ffi/class_base'
4
4
  require 'gir_ffi/type_map'
5
5
 
6
6
  require 'ffi-gobject_introspection'
7
+ require 'gir_ffi/info_ext'
7
8
 
9
+ require 'gir_ffi/in_pointer'
10
+ require 'gir_ffi/in_out_pointer'
8
11
  require 'gir_ffi/arg_helper'
12
+ require 'gir_ffi/callback'
13
+ require 'gir_ffi/callback_helper'
9
14
  require 'gir_ffi/builder'
10
15
 
11
16
  module GirFFI
@@ -59,7 +59,7 @@ module GirFFI
59
59
 
60
60
  def self.ptr_to_interface_array klass, ptr, size
61
61
  return [] if ptr.nil? or ptr.null?
62
- struct_size = klass.ffi_structure.size
62
+ struct_size = klass::Struct.size
63
63
  size.times.map do |idx|
64
64
  klass.wrap(ptr + struct_size * idx)
65
65
  end
@@ -0,0 +1,161 @@
1
+ require 'gir_ffi/base_argument_builder'
2
+
3
+ module GirFFI
4
+ # Implements building pre- and post-processing statements for arguments.
5
+ class ArgumentBuilder < BaseArgumentBuilder
6
+ def initialize var_gen, arginfo
7
+ super var_gen, arginfo.name, arginfo.argument_type, arginfo.direction
8
+ @arginfo = arginfo
9
+ end
10
+
11
+ def inarg
12
+ if has_input_value?
13
+ @array_arg.nil? ? @name : nil
14
+ end
15
+ end
16
+
17
+ def retname
18
+ if has_output_value?
19
+ @retname ||= @var_gen.new_var
20
+ end
21
+ end
22
+
23
+ def pre
24
+ pr = []
25
+ if has_input_value?
26
+ pr << fixed_array_size_check if needs_size_check?
27
+ pr << array_length_assignment if is_array_length_parameter?
28
+ end
29
+ pr << set_function_call_argument
30
+ pr
31
+ end
32
+
33
+ def post
34
+ result = []
35
+ 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}"
51
+ end
52
+ result
53
+ end
54
+
55
+ private
56
+
57
+ def is_array_length_parameter?
58
+ @array_arg
59
+ end
60
+
61
+ def needs_size_check?
62
+ specialized_type_tag == :c && type_info.array_fixed_size > -1
63
+ end
64
+
65
+ def is_fixed_length_array?
66
+ specialized_type_tag == :c
67
+ end
68
+
69
+ def fixed_array_size_check
70
+ size = type_info.array_fixed_size
71
+ "GirFFI::ArgHelper.check_fixed_array_size #{size}, #{@name}, \"#{@name}\""
72
+ end
73
+
74
+ def has_output_value?
75
+ @direction == :inout || @direction == :out
76
+ end
77
+
78
+ def has_input_value?
79
+ @direction == :inout || @direction == :in
80
+ end
81
+
82
+ def array_length_assignment
83
+ arrname = @array_arg.name
84
+ "#{@name} = #{arrname}.nil? ? 0 : #{arrname}.length"
85
+ end
86
+
87
+ def set_function_call_argument
88
+ value = if @direction == :out
89
+ if is_caller_allocated_object?
90
+ "#{argument_class_name}.allocate"
91
+ else
92
+ "GirFFI::InOutPointer.for #{type_specification}"
93
+ end
94
+ else
95
+ if needs_ingoing_parameter_conversion?
96
+ ingoing_parameter_conversion
97
+ else
98
+ @name
99
+ end
100
+ end
101
+ "#{callarg} = #{value}"
102
+ end
103
+
104
+ def is_caller_allocated_object?
105
+ [:object, :struct].include?(specialized_type_tag) &&
106
+ @arginfo.caller_allocates?
107
+ end
108
+
109
+ def needs_outgoing_parameter_conversion?
110
+ [ :array, :enum, :flags, :ghash, :glist, :gslist, :object, :struct,
111
+ :strv ].include?(specialized_type_tag)
112
+ end
113
+
114
+ def needs_ingoing_parameter_conversion?
115
+ @direction == :inout ||
116
+ [ :object, :struct, :callback, :utf8, :void, :glist, :gslist, :ghash,
117
+ :array, :c, :zero_terminated, :strv ].include?(specialized_type_tag)
118
+ end
119
+
120
+ def ingoing_parameter_conversion
121
+ case specialized_type_tag
122
+ when :enum, :flags
123
+ base = "#{argument_class_name}[#{parameter_conversion_arguments}]"
124
+ "GirFFI::InOutPointer.from #{specialized_type_tag.inspect}, #{base}"
125
+ when :object, :struct, :void, :glist, :gslist, :ghash, :array,
126
+ :zero_terminated, :strv, :callback
127
+ base = "#{argument_class_name}.from(#{parameter_conversion_arguments})"
128
+ if has_output_value?
129
+ if specialized_type_tag == :strv
130
+ "GirFFI::InOutPointer.from #{type_specification}, #{base}"
131
+ else
132
+ "GirFFI::InOutPointer.from :pointer, #{base}"
133
+ end
134
+ else
135
+ base
136
+ end
137
+ when :c, :utf8
138
+ if has_output_value?
139
+ "GirFFI::InOutPointer.from #{parameter_conversion_arguments}"
140
+ else
141
+ "GirFFI::InPointer.from(#{parameter_conversion_arguments})"
142
+ end
143
+ else
144
+ base = "#{parameter_conversion_arguments}"
145
+ "GirFFI::InOutPointer.from #{specialized_type_tag.inspect}, #{base}"
146
+ end
147
+ end
148
+
149
+ def output_conversion_arguments
150
+ conversion_arguments "#{callarg}.to_value"
151
+ end
152
+
153
+ def parameter_conversion_arguments
154
+ conversion_arguments @name
155
+ end
156
+
157
+ def self_t
158
+ type_tag.inspect
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,146 @@
1
+ module GirFFI
2
+ # Abstract parent class of the argument building classes. These
3
+ # classes are used by FunctionBuilder to create the code that
4
+ # processes each argument before and after the actual function call.
5
+ class BaseArgumentBuilder
6
+ KEYWORDS = [
7
+ "alias", "and", "begin", "break", "case", "class", "def", "do",
8
+ "else", "elsif", "end", "ensure", "false", "for", "if", "in",
9
+ "module", "next", "nil", "not", "or", "redo", "rescue", "retry",
10
+ "return", "self", "super", "then", "true", "undef", "unless",
11
+ "until", "when", "while", "yield"
12
+ ]
13
+
14
+ attr_reader :name, :retname
15
+
16
+ attr_accessor :length_arg, :array_arg
17
+
18
+ def initialize var_gen, name, typeinfo, direction
19
+ @var_gen = var_gen
20
+
21
+ @typeinfo = typeinfo
22
+ @direction = direction
23
+ @name = safe(name)
24
+
25
+ @inarg = nil
26
+ @retname = nil
27
+
28
+ @length_arg = nil
29
+ @array_arg = nil
30
+ end
31
+
32
+ def type_info
33
+ @typeinfo
34
+ end
35
+
36
+ def type_tag
37
+ type_info.tag
38
+ end
39
+
40
+ def specialized_type_tag
41
+ type_info.flattened_tag
42
+ end
43
+
44
+ def type_specification
45
+ type_info.type_specification
46
+ end
47
+
48
+ TAG_TO_WRAPPER_CLASS_MAP = {
49
+ :glist => 'GLib::List',
50
+ :gslist => 'GLib::SList',
51
+ :ghash => 'GLib::HashTable',
52
+ :array => 'GLib::Array',
53
+ :utf8 => 'GirFFI::InPointer',
54
+ :void => 'GirFFI::InPointer'
55
+ }
56
+
57
+ def argument_class_name
58
+ case (tag = type_info.flattened_tag)
59
+ when :struct, :union, :object, :interface, :enum, :flags
60
+ type_info.interface_type_name
61
+ when :callback
62
+ 'GirFFI::Callback'
63
+ when :byte_array
64
+ 'GLib::ByteArray'
65
+ when :array
66
+ 'GLib::Array'
67
+ when :ptr_array
68
+ 'GLib::PtrArray'
69
+ when :strv
70
+ 'GLib::Strv'
71
+ when :c, :zero_terminated
72
+ 'GirFFI::InPointer'
73
+ else
74
+ TAG_TO_WRAPPER_CLASS_MAP[tag]
75
+ end
76
+ end
77
+
78
+ def subtype_tag_or_class_name
79
+ type_info.subtype_tag_or_class_name
80
+ end
81
+
82
+ def elm_t
83
+ type_info.element_type.inspect
84
+ end
85
+
86
+ def array_size
87
+ if @length_arg
88
+ @length_arg.retname
89
+ else
90
+ type_info.array_fixed_size
91
+ end
92
+ end
93
+
94
+ def safe name
95
+ if KEYWORDS.include? name
96
+ "#{name}_"
97
+ else
98
+ name
99
+ end
100
+ end
101
+
102
+ def inarg
103
+ @array_arg.nil? ? @inarg : nil
104
+ end
105
+
106
+ def retval
107
+ @array_arg.nil? ? retname : nil
108
+ end
109
+
110
+ def callarg
111
+ @callarg ||= @var_gen.new_var
112
+ end
113
+
114
+ def pre
115
+ []
116
+ end
117
+
118
+ def post
119
+ []
120
+ end
121
+
122
+ def cleanup
123
+ []
124
+ end
125
+
126
+ private
127
+
128
+ def conversion_arguments name
129
+ case specialized_type_tag
130
+ when :utf8, :void
131
+ "#{self_t}, #{name}"
132
+ when :glist, :gslist, :ghash, :array
133
+ "#{elm_t}, #{name}"
134
+ when :c, :zero_terminated
135
+ "#{type_specification}, #{name}"
136
+ when :callback
137
+ iface = type_info.interface
138
+ "\"#{iface.namespace}\", \"#{iface.name}\", #{name}"
139
+ else
140
+ "#{name}"
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+