gir_ffi 0.9.4 → 0.9.5

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +11 -0
  3. data/README.md +8 -6
  4. data/TODO.md +3 -0
  5. data/lib/ffi-glib.rb +2 -1
  6. data/lib/ffi-gobject.rb +2 -1
  7. data/lib/ffi-gobject/object.rb +19 -9
  8. data/lib/ffi-gobject/value.rb +15 -3
  9. data/lib/gir_ffi-base.rb +9 -4
  10. data/lib/gir_ffi-base/glib.rb +8 -0
  11. data/lib/gir_ffi-base/glib/boolean.rb +1 -0
  12. data/lib/gir_ffi-base/glib/strv.rb +1 -0
  13. data/lib/gir_ffi-base/gobject.rb +5 -1
  14. data/lib/gir_ffi/boxed_base.rb +12 -0
  15. data/lib/gir_ffi/builder.rb +10 -1
  16. data/lib/gir_ffi/builders/argument_builder.rb +8 -4
  17. data/lib/gir_ffi/builders/base_return_value_builder.rb +38 -0
  18. data/lib/gir_ffi/builders/callback_return_value_builder.rb +2 -30
  19. data/lib/gir_ffi/builders/initializer_return_value_builder.rb +2 -6
  20. data/lib/gir_ffi/builders/module_builder.rb +2 -3
  21. data/lib/gir_ffi/builders/property_argument_builder.rb +23 -0
  22. data/lib/gir_ffi/builders/property_builder.rb +65 -46
  23. data/lib/gir_ffi/builders/property_return_value_builder.rb +14 -0
  24. data/lib/gir_ffi/builders/return_value_builder.rb +9 -33
  25. data/lib/gir_ffi/callback_base.rb +5 -0
  26. data/lib/gir_ffi/core.rb +3 -3
  27. data/lib/gir_ffi/in_pointer.rb +1 -1
  28. data/lib/gir_ffi/info_ext/i_signal_info.rb +2 -3
  29. data/lib/gir_ffi/info_ext/i_type_info.rb +22 -14
  30. data/lib/gir_ffi/interface_base.rb +12 -0
  31. data/lib/gir_ffi/user_defined_type_info.rb +8 -0
  32. data/lib/gir_ffi/version.rb +1 -1
  33. data/test/gir_ffi/builders/function_builder_test.rb +19 -0
  34. data/test/gir_ffi/builders/object_builder_test.rb +5 -11
  35. data/test/gir_ffi/builders/property_builder_test.rb +37 -5
  36. data/test/gir_ffi/builders/signal_closure_builder_test.rb +21 -0
  37. data/test/gir_ffi/builders/vfunc_builder_test.rb +20 -0
  38. data/test/gir_ffi/info_ext/i_type_info_test.rb +18 -0
  39. data/test/gir_ffi/user_defined_type_info_test.rb +25 -0
  40. data/test/gir_ffi_test_helper.rb +2 -6
  41. data/test/integration/generated_gimarshallingtests_test.rb +5 -5
  42. data/test/integration/generated_gio_test.rb +2 -3
  43. data/test/integration/generated_gst_test.rb +1 -0
  44. data/test/integration/generated_regress_test.rb +630 -189
  45. data/test/integration/generated_utility_test.rb +173 -0
  46. data/test/lib/Makefile.am +3 -5
  47. metadata +7 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 45d1fd64a20d066116552af625c33d0173bd6c47
4
- data.tar.gz: 404f1c8c32d94fff866f0e3499a62f4b9727ebc8
3
+ metadata.gz: 16ecb2c35535aff890ce4f63d90d9522a697c042
4
+ data.tar.gz: 54025535f0adadd1b3a1bc940d78ec7acbbdf47b
5
5
  SHA512:
6
- metadata.gz: 99533353d82d5700a0ecf734c4829157a51923b00b7bd40201dd760a8d6800865e6d00778182826565ac1ccf2bde68736d33cbb70116542ecf7d72e24a7d383e
7
- data.tar.gz: d9ddd4fe6a2017148a447d4ac8a9573905cd76cd73dabc7248f60fd75417f530751cf731286f5600e8c70baf89b97db73ff9847ef77505cf669f8231a63b8e75
6
+ metadata.gz: ae487826ba3c2f6e22ae78717b0f9523eb7d06e57a1892d52e50a950a925ae6cf18477bbf147c730b70e50b6c19373332f9b8409b0414a338e543ff3f7c7eea0
7
+ data.tar.gz: 16d9cf79dc31a6d5b591e4b835c1f3649414e9179a45e393c869bc8c5750b32573938b4817638b8d0355700a617951f828c3f11c435d1c7797aa0e63780dd9fc
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.5 / 2016-03-05
4
+
5
+ * Abort if modules were defined earlier, e.g., through the gems from the ruby-gnome family.
6
+ * Extend integration testing with GObjectIntrospection's test libraries.
7
+ * Find signals on user-defined types.
8
+ * Allow getting and setting of properties with a callback value.
9
+ * Handle pointer-like signal arguments such as GList.
10
+ * Handle static methods on interface modules.
11
+ * Free most self-allocated boxed types using GObject.boxed_free.
12
+ * Correctly assign length arguments for zero-terminated arguments
13
+
3
14
  ## 0.9.4 / 2016-02-22
4
15
 
5
16
  * Pass nil user data as null pointer, and store a missing callback as nil. This
data/README.md CHANGED
@@ -64,13 +64,15 @@ available under the name ending in plain `.so`. If GirFFI complains that it
64
64
  cannot find the library, try installing development packages for those
65
65
  libraries.
66
66
 
67
- GirFFI is developed on Debian sid, and tested through Travis CI on Ubuntu
68
- 12.04. Older versions of gobject-introspection than the ones used there
69
- are therefore not officially supported (although they may work).
67
+ GirFFI should work with gobject-introspection 1.32.0 and up.
70
68
 
71
- On Debian and Ubuntu, installing `libgirepository1.0-dev`,
72
- `gobject-introspection`, `gir1.2-gtop-2.0` and `gir1.2-gstreamer-1.0` should be
73
- enough to get `rake test` working.
69
+ On Debian and Ubuntu, installing `libgirepository1.0-1` and `gir1.2-glib-2.0`
70
+ should be enough to use GirFFI in your application.
71
+
72
+ To run the tests, you should additionally install `libgirepository1.0-dev`,
73
+ `gobject-introspection`, `gir1.2-gtop-2.0`, `gir1.2-pango-1.0`,
74
+ `gir1.2-secret-1` and `gir1.2-gstreamer-1.0`. This should be enough to get
75
+ `rake test` working.
74
76
 
75
77
  GirFFI has not been tested on Mac OS X or Microsoft Windows. YMMV.
76
78
 
data/TODO.md CHANGED
@@ -61,6 +61,9 @@ How about:
61
61
 
62
62
  This needs issue #63 to be resolved.
63
63
 
64
+ NOTE: When adding an interface module to a derived class, its prerequisites
65
+ should be checked.
66
+
64
67
  ## Persistent Ruby GObject identity
65
68
 
66
69
  GirFFI should make sure that if it gets a pointer to a GObject for which a Ruby
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  require 'gir_ffi/core'
3
3
 
4
- GirFFI.setup :GLib
4
+ # Bypass check for existing modules
5
+ GirFFI::Builders::ModuleBuilder.new('GLib').generate
5
6
 
6
7
  require 'ffi-glib/array'
7
8
  require 'ffi-glib/byte_array'
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  require 'gir_ffi/core'
3
3
 
4
- GirFFI.setup :GObject
4
+ # Bypass check for existing modules
5
+ GirFFI::Builders::ModuleBuilder.new('GObject').generate
5
6
 
6
7
  require 'ffi-gobject/base'
7
8
 
@@ -68,12 +68,7 @@ module GObject
68
68
  def get_property_extended(property_name)
69
69
  value = get_property(property_name)
70
70
  type_info = get_property_type property_name
71
- case type_info.tag
72
- when :ghash, :glist
73
- adjust_value_to_type value, type_info
74
- else
75
- value
76
- end
71
+ property_value_post_conversion value, type_info
77
72
  end
78
73
 
79
74
  def get_property_with_override(property_name)
@@ -84,8 +79,7 @@ module GObject
84
79
 
85
80
  def set_property_extended(property_name, value)
86
81
  type_info = get_property_type property_name
87
- adjusted_value = adjust_value_to_type(value, type_info)
88
-
82
+ adjusted_value = property_value_pre_conversion(value, type_info)
89
83
  set_property property_name, adjusted_value
90
84
  end
91
85
 
@@ -127,7 +121,21 @@ module GObject
127
121
  end
128
122
 
129
123
  # TODO: Move to ITypeInfo
130
- def adjust_value_to_type(val, type_info)
124
+ def property_value_post_conversion(val, type_info)
125
+ case type_info.flattened_tag
126
+ when :ghash
127
+ GLib::HashTable.from type_info.element_type, val
128
+ when :glist
129
+ GLib::List.from type_info.element_type, val
130
+ when :callback
131
+ GirFFI::Builder.build_class(type_info.interface).wrap val
132
+ else
133
+ val
134
+ end
135
+ end
136
+
137
+ # TODO: Move to ITypeInfo
138
+ def property_value_pre_conversion(val, type_info)
131
139
  case type_info.flattened_tag
132
140
  when :ghash
133
141
  GLib::HashTable.from type_info.element_type, val
@@ -135,6 +143,8 @@ module GObject
135
143
  GLib::List.from type_info.element_type, val
136
144
  when :strv
137
145
  GLib::Strv.from val
146
+ when :callback
147
+ GirFFI::Builder.build_class(type_info.interface).from val
138
148
  else
139
149
  val
140
150
  end
@@ -9,16 +9,22 @@ module GObject
9
9
  def init_with_finalizer(type)
10
10
  return self if [TYPE_NONE, TYPE_INVALID].include? type
11
11
  init_without_finalizer(type)
12
- ObjectSpace.define_finalizer self, self.class.make_finalizer(to_ptr)
13
12
  self
14
13
  end
15
14
 
16
15
  alias_method :init_without_finalizer, :init
17
16
  alias_method :init, :init_with_finalizer
18
17
 
19
- def self.make_finalizer(ptr)
18
+ def self.make_finalizer(struct, gtype)
20
19
  proc do
21
- GObject::Lib.g_value_unset ptr
20
+ ptr = struct.to_ptr
21
+ if ptr.autorelease?
22
+ ptr.autorelease = false
23
+ unless struct[:g_type] == TYPE_INVALID
24
+ GObject::Lib.g_value_unset ptr
25
+ end
26
+ GObject.boxed_free gtype, ptr
27
+ end
22
28
  end
23
29
  end
24
30
 
@@ -107,6 +113,12 @@ module GObject
107
113
  end
108
114
  end
109
115
 
116
+ def self.copy_value_to_pointer(value, pointer, offset = 0)
117
+ super(value, pointer, offset).tap do
118
+ value.to_ptr.autorelease = false if value
119
+ end
120
+ end
121
+
110
122
  private
111
123
 
112
124
  def set_ruby_value(val)
@@ -1,7 +1,12 @@
1
1
  # frozen_string_literal: true
2
- # This section contains code that is needed by GObjectIntrospection, but
3
- # belongs in modules that can only be created fully once GObjectIntrospection
4
- # is fully loaded.
5
- require 'gir_ffi-base/glib/boolean'
2
+ #
3
+ # This section contains code that is needed by GObjectIntrospection and GirFFI,
4
+ # but belongs in modules that can only be created fully once GirFFI is fully
5
+ # loaded.
6
+
7
+ # GLib::Strv and GObject.type_init are needed by GObjectIntrospection
6
8
  require 'gir_ffi-base/glib/strv'
7
9
  require 'gir_ffi-base/gobject'
10
+
11
+ # GLib::Boolean is needed by GirFFI.
12
+ require 'gir_ffi-base/glib/boolean'
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ensure GLib is defined by GirFFI itself
4
+ raise 'The module GLib was already defined elsewhere' if Kernel.const_defined? :GLib
5
+
6
+ # Module representing GLib's GLib namespace.
7
+ module GLib
8
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'ffi'
3
+ require 'gir_ffi-base/glib'
3
4
 
4
5
  module GLib
5
6
  # Implementation of gboolean
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'ffi'
3
+ require 'gir_ffi-base/glib'
3
4
 
4
5
  module GLib
5
6
  # Represents a null-terminated array of strings. GLib uses this
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require 'gir_ffi-base/gobject/lib'
2
+
3
+ # Ensure GLib is defined by GirFFI itself
4
+ raise 'The module GObject was already defined elsewhere' if Kernel.const_defined? :GObject
3
5
 
4
6
  # The part of the GObject namespace that is needed by GObjectIntrospection.
5
7
  module GObject
@@ -7,3 +9,5 @@ module GObject
7
9
  Lib.g_type_init
8
10
  end
9
11
  end
12
+
13
+ require 'gir_ffi-base/gobject/lib'
@@ -35,6 +35,18 @@ module GirFFI
35
35
 
36
36
  def initialize
37
37
  @struct = self.class::Struct.new
38
+ gtype = self.class.gtype
39
+ if GObject.type_fundamental(gtype) == GObject::TYPE_BOXED
40
+ ObjectSpace.define_finalizer self, self.class.make_finalizer(@struct, gtype)
41
+ end
42
+ end
43
+
44
+ def self.make_finalizer(struct, gtype)
45
+ proc do
46
+ ptr = struct.to_ptr
47
+ ptr.autorelease = false
48
+ GObject.boxed_free gtype, struct.to_ptr
49
+ end
38
50
  end
39
51
  end
40
52
  end
@@ -29,7 +29,16 @@ module GirFFI
29
29
  end
30
30
 
31
31
  def self.build_module(namespace, version = nil)
32
- Builders::ModuleBuilder.new(namespace, version).generate
32
+ module_name = namespace.gsub(/^./, &:upcase)
33
+ if Kernel.const_defined? module_name
34
+ modul = Kernel.const_get module_name
35
+ unless modul.const_defined? :GIR_FFI_BUILDER
36
+ raise "The module #{module_name} was already defined elsewhere"
37
+ end
38
+ end
39
+ Builders::ModuleBuilder.new(module_name,
40
+ namespace: namespace,
41
+ version: version).generate
33
42
  end
34
43
 
35
44
  # TODO: Move elsewhere, perhaps to FunctionBuilder.
@@ -120,17 +120,21 @@ module GirFFI
120
120
  "GirFFI::ArgHelper.check_fixed_array_size #{size}, #{name}, \"#{name}\""
121
121
  end
122
122
 
123
- def skipped?
123
+ def skipped_in?
124
+ @arginfo.skip?
125
+ end
126
+
127
+ def skipped_out?
124
128
  @arginfo.skip? ||
125
129
  @array_arg && @array_arg.specialized_type_tag == :strv
126
130
  end
127
131
 
128
132
  def has_output_value?
129
- (direction == :inout || direction == :out) && !skipped?
133
+ (direction == :inout || direction == :out) && !skipped_out?
130
134
  end
131
135
 
132
136
  def has_input_value?
133
- has_ingoing_component? && !skipped?
137
+ has_ingoing_component? && !skipped_in?
134
138
  end
135
139
 
136
140
  def has_ingoing_component?
@@ -163,7 +167,7 @@ module GirFFI
163
167
  DESTROY_NOTIFIER = 'GLib::DestroyNotify.default'.freeze
164
168
 
165
169
  def ingoing_convertor
166
- if skipped?
170
+ if skipped_in?
167
171
  NullConvertor.new('0')
168
172
  elsif destroy_notifier?
169
173
  NullConvertor.new(DESTROY_NOTIFIER)
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+ require 'gir_ffi/builders/base_argument_builder'
3
+
4
+ module GirFFI
5
+ module Builders
6
+ # Implements building post-processing statements for return values of
7
+ # callbacks.
8
+ class BaseReturnValueBuilder < BaseArgumentBuilder
9
+ def relevant?
10
+ !void_return_value? && !arginfo.skip?
11
+ end
12
+
13
+ def capture_variable_name
14
+ @capture_variable_name ||= new_variable if relevant?
15
+ end
16
+
17
+ def post_converted_name
18
+ @post_converted_name ||= if has_post_conversion?
19
+ new_variable
20
+ else
21
+ capture_variable_name
22
+ end
23
+ end
24
+
25
+ def return_value_name
26
+ post_converted_name if has_return_value_name?
27
+ end
28
+
29
+ def void_return_value?
30
+ specialized_type_tag == :void && !type_info.pointer?
31
+ end
32
+
33
+ def has_return_value_name?
34
+ relevant? && !array_arg
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,32 +1,12 @@
1
1
  # frozen_string_literal: true
2
- require 'gir_ffi/builders/return_value_builder'
2
+ require 'gir_ffi/builders/base_return_value_builder'
3
3
  require 'gir_ffi/builders/ruby_to_c_convertor'
4
4
 
5
5
  module GirFFI
6
6
  module Builders
7
7
  # Implements building post-processing statements for return values of
8
8
  # callbacks.
9
- class CallbackReturnValueBuilder < BaseArgumentBuilder
10
- def relevant?
11
- !void_return_value? && !arginfo.skip?
12
- end
13
-
14
- def capture_variable_name
15
- @capture_variable_name ||= new_variable if relevant?
16
- end
17
-
18
- def post_converted_name
19
- @post_converted_name ||= if has_post_conversion?
20
- new_variable
21
- else
22
- capture_variable_name
23
- end
24
- end
25
-
26
- def return_value_name
27
- post_converted_name if has_return_value_name?
28
- end
29
-
9
+ class CallbackReturnValueBuilder < BaseReturnValueBuilder
30
10
  def post_conversion
31
11
  if has_post_conversion?
32
12
  if type_info.flattened_tag == :object
@@ -60,14 +40,6 @@ module GirFFI
60
40
  capture_variable_name
61
41
  end
62
42
  end
63
-
64
- def void_return_value?
65
- specialized_type_tag == :void && !type_info.pointer?
66
- end
67
-
68
- def has_return_value_name?
69
- relevant? && !array_arg
70
- end
71
43
  end
72
44
  end
73
45
  end
@@ -1,14 +1,10 @@
1
1
  # frozen_string_literal: true
2
- require 'gir_ffi/builders/base_argument_builder'
2
+ require 'gir_ffi/builders/base_return_value_builder'
3
3
 
4
4
  module GirFFI
5
5
  module Builders
6
6
  # Implements post-conversion for initializer functions
7
- class InitializerReturnValueBuilder < BaseArgumentBuilder
8
- def capture_variable_name
9
- @capture_variable_name ||= new_variable
10
- end
11
-
7
+ class InitializerReturnValueBuilder < BaseReturnValueBuilder
12
8
  def post_conversion
13
9
  ["store_pointer(#{capture_variable_name})"]
14
10
  end
@@ -12,11 +12,10 @@ module GirFFI
12
12
  class ModuleBuilder
13
13
  include BuilderHelper
14
14
 
15
- def initialize(namespace, version = nil)
15
+ def initialize(module_name, namespace: module_name, version: nil)
16
16
  @namespace = namespace
17
17
  @version = version
18
- # FIXME: Pass safe namespace as an argument
19
- @safe_namespace = @namespace.gsub(/^./, &:upcase)
18
+ @safe_namespace = module_name
20
19
  end
21
20
 
22
21
  def generate
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ require 'gir_ffi/builders/base_argument_builder'
3
+
4
+ module GirFFI
5
+ module Builders
6
+ # Convertor for arguments for property setters.
7
+ class PropertyArgumentBuilder < BaseArgumentBuilder
8
+ def pre_conversion
9
+ pr = []
10
+ pr << "#{call_argument_name} = #{ingoing_convertor.conversion}"
11
+ pr
12
+ end
13
+
14
+ def ingoing_convertor
15
+ if type_info.needs_ruby_to_c_conversion_for_properties?
16
+ RubyToCConvertor.new(type_info, name)
17
+ else
18
+ NullConvertor.new(name)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end