gir_ffi 0.8.6 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +18 -0
  3. data/README.md +3 -4
  4. data/lib/ffi-glib.rb +1 -0
  5. data/lib/ffi-glib/container_class_methods.rb +12 -0
  6. data/lib/ffi-glib/destroy_notify.rb +15 -0
  7. data/lib/ffi-glib/main_loop.rb +23 -4
  8. data/lib/ffi-gobject.rb +4 -2
  9. data/lib/ffi-gobject/object.rb +31 -16
  10. data/lib/ffi-gobject/object_class.rb +4 -0
  11. data/lib/ffi-gobject/value.rb +3 -3
  12. data/lib/ffi-gobject_introspection/i_flags_info.rb +0 -1
  13. data/lib/gir_ffi-base/gobject/lib.rb +10 -0
  14. data/lib/gir_ffi/arg_helper.rb +1 -22
  15. data/lib/gir_ffi/boxed_base.rb +1 -0
  16. data/lib/gir_ffi/builder.rb +7 -1
  17. data/lib/gir_ffi/builders/argument_builder.rb +21 -9
  18. data/lib/gir_ffi/builders/argument_builder_collection.rb +28 -9
  19. data/lib/gir_ffi/builders/base_argument_builder.rb +36 -12
  20. data/lib/gir_ffi/builders/base_method_builder.rb +1 -1
  21. data/lib/gir_ffi/builders/callback_argument_builder.rb +4 -0
  22. data/lib/gir_ffi/builders/closure_to_pointer_convertor.rb +3 -2
  23. data/lib/gir_ffi/builders/constructor_builder.rb +1 -1
  24. data/lib/gir_ffi/builders/enum_builder.rb +4 -4
  25. data/lib/gir_ffi/builders/error_argument_builder.rb +4 -0
  26. data/lib/gir_ffi/builders/field_builder.rb +23 -9
  27. data/lib/gir_ffi/builders/flags_builder.rb +28 -0
  28. data/lib/gir_ffi/builders/full_c_to_ruby_convertor.rb +18 -0
  29. data/lib/gir_ffi/builders/module_builder.rb +1 -0
  30. data/lib/gir_ffi/builders/null_argument_builder.rb +9 -1
  31. data/lib/gir_ffi/builders/object_builder.rb +7 -4
  32. data/lib/gir_ffi/builders/property_builder.rb +2 -2
  33. data/lib/gir_ffi/builders/return_value_builder.rb +4 -4
  34. data/lib/gir_ffi/builders/struct_builder.rb +10 -2
  35. data/lib/gir_ffi/builders/type_builder.rb +12 -9
  36. data/lib/gir_ffi/builders/unintrospectable_boxed_builder.rb +26 -0
  37. data/lib/gir_ffi/builders/user_defined_builder.rb +2 -2
  38. data/lib/gir_ffi/builders/with_layout.rb +1 -1
  39. data/lib/gir_ffi/callback_base.rb +13 -5
  40. data/lib/gir_ffi/core.rb +1 -0
  41. data/lib/gir_ffi/error_argument_info.rb +4 -0
  42. data/lib/gir_ffi/flags_base.rb +63 -0
  43. data/lib/gir_ffi/in_pointer.rb +1 -3
  44. data/lib/gir_ffi/info_ext/i_type_info.rb +6 -0
  45. data/lib/gir_ffi/object_base.rb +9 -1
  46. data/lib/gir_ffi/object_store.rb +26 -0
  47. data/lib/gir_ffi/unintrospectable_boxed_info.rb +31 -0
  48. data/lib/gir_ffi/unintrospectable_type_info.rb +5 -0
  49. data/lib/gir_ffi/user_defined_type_info.rb +19 -0
  50. data/lib/gir_ffi/version.rb +1 -1
  51. data/test/ffi-glib/destroy_notify_test.rb +13 -0
  52. data/test/ffi-glib/main_loop_test.rb +3 -3
  53. data/test/ffi-gobject/object_class_test.rb +8 -0
  54. data/test/ffi-gobject/object_test.rb +23 -5
  55. data/test/ffi-gobject/value_test.rb +19 -5
  56. data/test/ffi-gobject_test.rb +2 -2
  57. data/test/gir_ffi/builders/argument_builder_test.rb +12 -2
  58. data/test/gir_ffi/builders/constructor_builder_test.rb +4 -4
  59. data/test/gir_ffi/builders/function_builder_test.rb +46 -3
  60. data/test/gir_ffi/builders/object_builder_test.rb +25 -0
  61. data/test/gir_ffi/builders/property_builder_test.rb +4 -4
  62. data/test/gir_ffi/builders/struct_builder_test.rb +15 -13
  63. data/test/gir_ffi/builders/unintrospectable_boxed_builder_test.rb +33 -0
  64. data/test/gir_ffi/builders/unintrospectable_builder_test.rb +6 -0
  65. data/test/gir_ffi/builders/user_defined_builder_test.rb +7 -1
  66. data/test/gir_ffi/callback_base_test.rb +12 -2
  67. data/test/gir_ffi/object_base_test.rb +14 -0
  68. data/test/integration/callback_exceptions_test.rb +61 -0
  69. data/test/integration/generated_gimarshallingtests_test.rb +70 -70
  70. data/test/integration/generated_gio_test.rb +1 -1
  71. data/test/integration/generated_gobject_test.rb +1 -1
  72. data/test/integration/generated_gtop_test.rb +5 -1
  73. data/test/integration/generated_regress_test.rb +83 -102
  74. data/test/integration/generated_warnlib_test.rb +2 -2
  75. metadata +42 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fffb54bf2eca76e21e43bb5838e0f307063c2b6d
4
- data.tar.gz: 4ab64e4d22d1deba88e930a3a7b046a19558b6aa
3
+ metadata.gz: 107172036ec9fdf82546c5500d102f21b5776298
4
+ data.tar.gz: 21833bf950d07a14f07b7f95d6a59ec12661ea15
5
5
  SHA512:
6
- metadata.gz: 482f25f7934b20c3cb1768225f630081198b321e081c3ae74d70d6c7bd9f8ed45f10dc6c40bbca2d247d9637909e134e988b59811354f6f77f71cb392c45c60c
7
- data.tar.gz: 8b0ed87c864d9af6f5b8c80f02bc457f0a0858a3c00f53d48b8b22e0cfe5fae768ae730b7b00c939efad503581cf126fd5c4e75f51a18d5957846e3c8c9795d0
6
+ metadata.gz: 7ce027fd3bd08475eb90d7387cef5f48676db5eef27eba9fcfb86d06e6e3cea50a508f76af91f86418d99803f92e6ebe096986451373582780ab299ec506e5cd
7
+ data.tar.gz: 7b83c445f3ced66bb2ec47fe026e4fb12f54e76b5896bdc0b7703953e4fc3003ce0ca5986cdb225e9e52992cd6e5bf21b1df89a894fe6f334b23b0ec95708b31
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0 / 2016-01-21
4
+
5
+ * Propagate exceptions from callbacks during event loops
6
+ * Make default object constructor take a hash of properties
7
+ * Fix implementation of ObjectBase.object_class
8
+ * Make object class struct types inherit from their parent structs. This makes
9
+ parent methods and fields available.
10
+ * Use ObjectBase.object_class instead of old Object#type_class to find
11
+ properties
12
+ * Remove Object#type_class
13
+ * Automatically unpack GValue return values
14
+ * Use a BitMask to handle flag values
15
+ * Handle callback arguments as Ruby block arguments
16
+ * Use user data and destroy notify arguments to automate callback cleanup. This
17
+ means you can no longer supply your own user data and notifiers.
18
+ * Support CRuby 2.3 and Rubinius 3.x
19
+ * Drop support for JRuby 1.7 and Rubinius 2.x.
20
+
3
21
  ## 0.8.6 / 2015-12-09
4
22
 
5
23
  * Change handling of initializers in subclasses
data/README.md CHANGED
@@ -48,9 +48,8 @@ See the [documentation](docs/Documentation.md) for more usage information.
48
48
 
49
49
  ## Requirements
50
50
 
51
- GirFFI should work on CRuby 2.0.0, 2.1 and 2.2, JRuby 1.7.x in 1.9 or 2.0 mode,
52
- JRuby 9.0.0.0, and on Rubinius. If you need support for CRuby 1.9.3, use
53
- version 0.7.10.
51
+ GirFFI is tested on CRuby 2.0.0, 2.1, 2.2 and 2.3, JRuby 9.0.0.0, and on
52
+ Rubinius 3.
54
53
 
55
54
  You will also need gobject-introspection installed with some
56
55
  introspection data.
@@ -113,7 +112,7 @@ The following people have contributed to GirFFI over the years:
113
112
 
114
113
  ## License
115
114
 
116
- Copyright © 2009–2015 [Matijs van Zuijlen](http://www.matijs.net)
115
+ Copyright © 2009–2016 [Matijs van Zuijlen](http://www.matijs.net)
117
116
 
118
117
  GirFFI is free software, distributed under the terms of the GNU Lesser
119
118
  General Public License, version 2.1 or later. See the file COPYING.LIB for
@@ -5,6 +5,7 @@ GirFFI.setup :GLib
5
5
  require 'ffi-glib/array'
6
6
  require 'ffi-glib/byte_array'
7
7
  require 'ffi-glib/bytes'
8
+ require 'ffi-glib/destroy_notify'
8
9
  require 'ffi-glib/error'
9
10
  require 'ffi-glib/hash_table'
10
11
  require 'ffi-glib/iconv'
@@ -3,6 +3,16 @@ module GLib
3
3
  # HashTable.
4
4
  module ContainerClassMethods
5
5
  def wrap(typespec, ptr)
6
+ # HACK: wrap and from are almost the same!
7
+ ptr = case ptr
8
+ when nil
9
+ nil
10
+ when FFI::Pointer
11
+ ptr
12
+ when GirFFI::BoxedBase
13
+ ptr.to_ptr
14
+ end
15
+
6
16
  super(ptr).tap do |container|
7
17
  container.reset_typespec typespec if container
8
18
  end
@@ -16,6 +26,8 @@ module GLib
16
26
  wrap typespec, it
17
27
  when self
18
28
  it.reset_typespec typespec
29
+ when GirFFI::BoxedBase
30
+ wrap typespec, it.to_ptr
19
31
  else
20
32
  from_enumerable typespec, it
21
33
  end
@@ -0,0 +1,15 @@
1
+ GLib.load_class :DestroyNotify
2
+
3
+ module GLib
4
+ # Overrides for DestroyNotify, the callback type for destroy notifications.
5
+ # It should not be necessary to create objects of this class from Ruby
6
+ # directly.
7
+ class DestroyNotify
8
+ def self.default
9
+ @default ||= from proc { |user_data|
10
+ callback_key = GirFFI::ArgHelper::OBJECT_STORE.fetch(user_data)
11
+ drop_callback callback_key
12
+ }
13
+ end
14
+ end
15
+ end
@@ -18,9 +18,8 @@ module GLib
18
18
  end
19
19
 
20
20
  def setup_idle_handler
21
- @handler_id ||= GLib.timeout_add(GLib::PRIORITY_DEFAULT,
22
- @timeout, handler_proc,
23
- nil, nil)
21
+ @handler_id ||=
22
+ GLib.timeout_add(GLib::PRIORITY_DEFAULT, @timeout, &handler_proc)
24
23
  end
25
24
 
26
25
  private
@@ -33,6 +32,11 @@ module GLib
33
32
  end
34
33
  end
35
34
 
35
+ EXCEPTIONS = []
36
+ RUNNING_LOOPS = []
37
+
38
+ setup_instance_method :run
39
+
36
40
  def run_with_thread_enabler
37
41
  case RUBY_ENGINE
38
42
  when 'jruby'
@@ -40,7 +44,22 @@ module GLib
40
44
  else # 'ruby' most likely
41
45
  ThreadEnabler.instance.setup_idle_handler
42
46
  end
43
- run_without_thread_enabler
47
+ RUNNING_LOOPS << self
48
+ result = run_without_thread_enabler
49
+ ex = EXCEPTIONS.shift
50
+ RUNNING_LOOPS.pop
51
+ raise ex if ex
52
+ result
53
+ end
54
+
55
+ def self.handle_exception(ex)
56
+ current_loop = RUNNING_LOOPS.last
57
+ if current_loop
58
+ EXCEPTIONS << ex
59
+ current_loop.quit
60
+ else
61
+ raise ex
62
+ end
44
63
  end
45
64
 
46
65
  alias_method :run_without_thread_enabler, :run
@@ -51,7 +51,7 @@ module GObject
51
51
  # NOTE: Depending on the version of GObjectIntrospection, the result will
52
52
  # be stored in result or return_gvalue. This was changed between versions
53
53
  # 1.44 and 1.46.
54
- result || return_gvalue
54
+ result || return_gvalue.get_value
55
55
  end
56
56
 
57
57
  def self.signal_connect(object, detailed_signal, data = nil, after = false, &block)
@@ -59,7 +59,9 @@ module GObject
59
59
  signal_name, = detailed_signal.split('::')
60
60
  sig_info = object.class.find_signal signal_name
61
61
 
62
- closure = sig_info.wrap_in_closure { |*args| block.call(*args << data) }
62
+ closure = sig_info.wrap_in_closure do |*args|
63
+ block.call(*args << data)
64
+ end
63
65
 
64
66
  signal_connect_closure object, detailed_signal, closure, after
65
67
  end
@@ -5,8 +5,18 @@ module GObject
5
5
  class Object
6
6
  setup_method 'new'
7
7
 
8
- def initialize_with_automatic_gtype(properties)
9
- initialize_without_automatic_gtype(self.class.gtype, properties)
8
+ def initialize_with_automatic_gtype(properties = {})
9
+ gparameters = properties.map do |name, value|
10
+ name = name.to_s
11
+ unless property_param_spec(name)
12
+ raise ArgumentError, "Property '#{name}' not found in class #{self.class}"
13
+ end
14
+ GObject::Parameter.new.tap do |gparam|
15
+ gparam.name = name
16
+ gparam.value = value
17
+ end
18
+ end
19
+ initialize_without_automatic_gtype(self.class.gtype, gparameters)
10
20
  end
11
21
 
12
22
  alias_method :initialize_without_automatic_gtype, :initialize
@@ -55,23 +65,20 @@ module GObject
55
65
  setup_instance_method 'set_property'
56
66
 
57
67
  def get_property_extended(property_name)
58
- gvalue = get_property property_name
68
+ value = get_property(property_name)
59
69
  type_info = get_property_type property_name
60
70
  case type_info.tag
61
71
  when :ghash, :glist
62
- adjust_value_to_type gvalue.get_value_plain, type_info
72
+ adjust_value_to_type value, type_info
63
73
  else
64
- gvalue.get_value
74
+ value
65
75
  end
66
76
  end
67
77
 
68
78
  def get_property_with_override(property_name)
69
- pspec = type_class.find_property property_name
70
-
71
- gvalue = GObject::Value.for_gtype pspec.value_type
79
+ gvalue = gvalue_for_property property_name
72
80
  get_property_without_override property_name, gvalue
73
-
74
- gvalue
81
+ gvalue.get_value
75
82
  end
76
83
 
77
84
  def set_property_extended(property_name, value)
@@ -82,16 +89,11 @@ module GObject
82
89
  end
83
90
 
84
91
  def set_property_with_override(property_name, value)
85
- pspec = type_class.find_property property_name
86
- gvalue = GObject::Value.for_gtype pspec.value_type
92
+ gvalue = gvalue_for_property(property_name)
87
93
  gvalue.set_value value
88
94
  set_property_without_override property_name, gvalue
89
95
  end
90
96
 
91
- def type_class
92
- GObject::ObjectClass.wrap(to_ptr.get_pointer 0)
93
- end
94
-
95
97
  alias_method :get_property_without_override, :get_property
96
98
  alias_method :get_property, :get_property_with_override
97
99
 
@@ -108,6 +110,19 @@ module GObject
108
110
  prop.property_type
109
111
  end
110
112
 
113
+ def gvalue_for_property(property_name)
114
+ gtype = property_gtype property_name
115
+ GObject::Value.for_gtype gtype
116
+ end
117
+
118
+ def property_gtype(property_name)
119
+ property_param_spec(property_name).value_type
120
+ end
121
+
122
+ def property_param_spec(property_name)
123
+ object_class.find_property property_name
124
+ end
125
+
111
126
  # TODO: Move to ITypeInfo
112
127
  def adjust_value_to_type(val, type_info)
113
128
  case type_info.flattened_tag
@@ -10,5 +10,9 @@ module GObject
10
10
  def get_property=(callback)
11
11
  @struct[:get_property] = GObject::ObjectGetPropertyFunc.from callback
12
12
  end
13
+
14
+ def gtype
15
+ GirFFI::InOutPointer.new(:GType, to_ptr).to_value
16
+ end
13
17
  end
14
18
  end
@@ -7,9 +7,9 @@ module GObject
7
7
 
8
8
  def init_with_finalizer(type)
9
9
  return self if [TYPE_NONE, TYPE_INVALID].include? type
10
- init_without_finalizer(type).tap do
11
- ObjectSpace.define_finalizer self, self.class.make_finalizer(to_ptr)
12
- end
10
+ init_without_finalizer(type)
11
+ ObjectSpace.define_finalizer self, self.class.make_finalizer(to_ptr)
12
+ self
13
13
  end
14
14
 
15
15
  alias_method :init_without_finalizer, :init
@@ -1,6 +1,5 @@
1
1
  module GObjectIntrospection
2
2
  # Wraps a GIEnumInfo struct, if it represents a flag type.
3
- # TODO: Perhaps just use IEnumInfo. Seems to make more sense.
4
3
  class IFlagsInfo < IEnumInfo
5
4
  end
6
5
  end
@@ -1,7 +1,17 @@
1
+ require 'ffi/bit_masks'
2
+
3
+ # NOTE: Monkey-patch BitMask to work on JRuby.
4
+ class FFI::BitMasks::BitMask
5
+ def reference_required?
6
+ false
7
+ end
8
+ end
9
+
1
10
  module GObject
2
11
  # Module for attaching functions from the gobject library
3
12
  module Lib
4
13
  extend FFI::Library
14
+ extend FFI::BitMasks
5
15
  ffi_lib 'gobject-2.0'
6
16
  attach_function :g_type_init, [], :void
7
17
  end
@@ -1,33 +1,12 @@
1
1
  require 'gir_ffi/allocation_helper'
2
2
  require 'gir_ffi/builder'
3
3
  require 'gir_ffi/glib_error'
4
+ require 'gir_ffi/object_store'
4
5
 
5
6
  module GirFFI
6
7
  # Helper module containing methods used during argument conversion in
7
8
  # generated methods.
8
9
  module ArgHelper
9
- # Helper class for storing objects for later retrieval. Used to store user
10
- # data arguments.
11
- class ObjectStore
12
- def initialize
13
- @store = {}
14
- end
15
-
16
- def store(ptr, obj)
17
- @store[ptr.address] = obj
18
- end
19
-
20
- def fetch(ptr)
21
- return if ptr.null?
22
- key = ptr.address
23
- if @store.key? key
24
- @store[key]
25
- else
26
- ptr
27
- end
28
- end
29
- end
30
-
31
10
  OBJECT_STORE = ObjectStore.new
32
11
 
33
12
  def self.ptr_to_utf8_length(ptr, len)
@@ -13,6 +13,7 @@ module GirFFI
13
13
  self
14
14
  end
15
15
 
16
+ # NOTE: Needed for JRuby's FFI
16
17
  def self.to_native(value, _context)
17
18
  value.struct
18
19
  end
@@ -2,6 +2,7 @@ require 'gir_ffi/builders/type_builder'
2
2
  require 'gir_ffi/builders/module_builder'
3
3
  require 'gir_ffi/builder_helper'
4
4
  require 'gir_ffi/unintrospectable_type_info'
5
+ require 'gir_ffi/unintrospectable_boxed_info'
5
6
 
6
7
  module GirFFI
7
8
  # Builds modules and classes based on information found in the
@@ -16,7 +17,12 @@ module GirFFI
16
17
 
17
18
  def self.build_by_gtype(gtype)
18
19
  info = GObjectIntrospection::IRepository.default.find_by_gtype gtype
19
- info ||= UnintrospectableTypeInfo.new gtype
20
+ info ||= case GObject.type_fundamental gtype
21
+ when GObject::TYPE_BOXED
22
+ UnintrospectableBoxedInfo.new gtype
23
+ when GObject::TYPE_OBJECT
24
+ UnintrospectableTypeInfo.new gtype
25
+ end
20
26
 
21
27
  build_class info
22
28
  end
@@ -1,6 +1,6 @@
1
1
  require 'gir_ffi/builders/base_argument_builder'
2
2
  require 'gir_ffi/builders/closure_to_pointer_convertor'
3
- require 'gir_ffi/builders/c_to_ruby_convertor'
3
+ require 'gir_ffi/builders/full_c_to_ruby_convertor'
4
4
  require 'gir_ffi/builders/ruby_to_c_convertor'
5
5
  require 'gir_ffi/builders/null_convertor'
6
6
 
@@ -9,7 +9,12 @@ module GirFFI
9
9
  # Implements building pre- and post-processing statements for arguments.
10
10
  class ArgumentBuilder < BaseArgumentBuilder
11
11
  def method_argument_name
12
- name if has_input_value? && !array_length_parameter?
12
+ name if has_input_value? && !helper_argument?
13
+ end
14
+
15
+ # TODO: Improve this so each method can only have one block argument.
16
+ def block_argument?
17
+ specialized_type_tag == :callback
13
18
  end
14
19
 
15
20
  def post_converted_name
@@ -60,13 +65,16 @@ module GirFFI
60
65
  private
61
66
 
62
67
  def has_post_conversion?
63
- has_output_value? && !caller_allocated_object?
68
+ has_output_value? && (!caller_allocated_object? || gvalue?)
64
69
  end
65
70
 
66
71
  def output_value
72
+ if caller_allocated_object? && gvalue?
73
+ return "#{call_argument_name}.get_value"
74
+ end
67
75
  base = "#{call_argument_name}.to_value"
68
76
  if needs_out_conversion?
69
- CToRubyConvertor.new(@type_info, base, length_argument_name).conversion
77
+ FullCToRubyConvertor.new(@type_info, base, length_argument_name).conversion
70
78
  elsif allocated_by_them?
71
79
  "GirFFI::InOutPointer.new(#{type_info.tag_or_class[1].inspect}, #{base}).to_value"
72
80
  else
@@ -78,6 +86,10 @@ module GirFFI
78
86
  @type_info.needs_c_to_ruby_conversion_for_functions?
79
87
  end
80
88
 
89
+ def gvalue?
90
+ @type_info.gvalue?
91
+ end
92
+
81
93
  # Check if an out argument needs to be allocated by them, the callee. Since
82
94
  # caller_allocates is false by default, we must also check that the type
83
95
  # is a pointer. For example, an out parameter of type gint8* will always
@@ -90,10 +102,6 @@ module GirFFI
90
102
  length_arg && length_arg.post_converted_name
91
103
  end
92
104
 
93
- def array_length_parameter?
94
- @array_arg
95
- end
96
-
97
105
  def needs_size_check?
98
106
  specialized_type_tag == :c && type_info.array_fixed_size > -1
99
107
  end
@@ -139,11 +147,15 @@ module GirFFI
139
147
  @arginfo.caller_allocates?
140
148
  end
141
149
 
150
+ DESTROY_NOTIFIER = 'GLib::DestroyNotify.default'
151
+
142
152
  def ingoing_convertor
143
153
  if skipped?
144
154
  NullConvertor.new('0')
155
+ elsif destroy_notifier?
156
+ NullConvertor.new(DESTROY_NOTIFIER)
145
157
  elsif closure?
146
- ClosureToPointerConvertor.new(pre_convertor_argument)
158
+ ClosureToPointerConvertor.new(pre_convertor_argument, @is_closure)
147
159
  elsif @type_info.needs_ruby_to_c_conversion_for_functions?
148
160
  RubyToCConvertor.new(@type_info, pre_convertor_argument)
149
161
  else