gir_ffi 0.8.6 → 0.9.0

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 (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
@@ -1,10 +1,12 @@
1
1
  require 'gir_ffi/builders/callback_builder'
2
2
  require 'gir_ffi/builders/constant_builder'
3
3
  require 'gir_ffi/builders/enum_builder'
4
+ require 'gir_ffi/builders/flags_builder'
4
5
  require 'gir_ffi/builders/interface_builder'
5
6
  require 'gir_ffi/builders/object_builder'
6
7
  require 'gir_ffi/builders/struct_builder'
7
8
  require 'gir_ffi/builders/signal_closure_builder'
9
+ require 'gir_ffi/builders/unintrospectable_boxed_builder'
8
10
  require 'gir_ffi/builders/unintrospectable_builder'
9
11
  require 'gir_ffi/builders/union_builder'
10
12
  require 'gir_ffi/builders/vfunc_builder'
@@ -17,15 +19,16 @@ module GirFFI
17
19
  CACHE = {}
18
20
 
19
21
  TYPE_MAP = {
20
- callback: CallbackBuilder,
21
- constant: ConstantBuilder,
22
- enum: EnumBuilder,
23
- flags: EnumBuilder,
24
- interface: InterfaceBuilder,
25
- object: ObjectBuilder,
26
- struct: StructBuilder,
27
- union: UnionBuilder,
28
- unintrospectable: UnintrospectableBuilder
22
+ callback: CallbackBuilder,
23
+ constant: ConstantBuilder,
24
+ enum: EnumBuilder,
25
+ flags: FlagsBuilder,
26
+ interface: InterfaceBuilder,
27
+ object: ObjectBuilder,
28
+ struct: StructBuilder,
29
+ union: UnionBuilder,
30
+ unintrospectable_boxed: UnintrospectableBoxedBuilder,
31
+ unintrospectable: UnintrospectableBuilder
29
32
  }
30
33
 
31
34
  def self.build(info)
@@ -0,0 +1,26 @@
1
+ require 'gir_ffi/builders/boxed_builder'
2
+
3
+ module GirFFI
4
+ module Builders
5
+ # Implements the creation of a class representing a boxed type for
6
+ # which no data is found in the GIR.
7
+ class UnintrospectableBoxedBuilder < BoxedBuilder
8
+ def klass
9
+ @klass ||= TypeBuilder::CACHE[target_gtype] ||= Class.new(superclass)
10
+ end
11
+
12
+ def setup_class
13
+ setup_layout
14
+ setup_constants
15
+ end
16
+
17
+ def superclass
18
+ BoxedBase
19
+ end
20
+
21
+ def layout_superclass
22
+ FFI::Struct
23
+ end
24
+ end
25
+ end
26
+ end
@@ -35,11 +35,11 @@ module GirFFI
35
35
  end
36
36
 
37
37
  def parent_info
38
- @parent_info ||= gir.find_by_gtype(parent_gtype.to_i)
38
+ @info.parent
39
39
  end
40
40
 
41
41
  def parent_gtype
42
- @parent_gtype ||= GType.new(klass.superclass.gtype)
42
+ @info.parent_gtype
43
43
  end
44
44
 
45
45
  def interface_gtypes
@@ -4,7 +4,7 @@ module GirFFI
4
4
  module Builders
5
5
  # Implements the creation of classes representing types with layout,
6
6
  # i.e., :union, :struct, :object.
7
- # Note: This module depends on methods in RegisteredTypeBuilder.
7
+ # NOTE: This module depends on methods in RegisteredTypeBuilder.
8
8
  module WithLayout
9
9
  def layout_specification
10
10
  spec = base_layout_specification
@@ -31,25 +31,33 @@ module GirFFI
31
31
  from_native ptr, nil
32
32
  end
33
33
 
34
- CALLBACKS = []
34
+ CALLBACKS = {}
35
35
 
36
36
  def self.store_callback(prc)
37
- CALLBACKS << prc
37
+ CALLBACKS[prc.object_id] = prc
38
+ end
39
+
40
+ def self.drop_callback(key)
41
+ CALLBACKS.delete key
38
42
  end
39
43
 
40
44
  # Create Callback from a Proc. Makes sure arguments are properly wrapped,
41
45
  # and the callback is stored to prevent garbage collection.
42
46
  def self.from(prc)
43
- wrap_in_callback_args_mapper(prc).tap do |cb|
47
+ wrap_proc(prc).tap do |cb|
44
48
  store_callback cb
45
49
  end
46
50
  end
47
51
 
48
- def self.wrap_in_callback_args_mapper(prc)
52
+ def self.wrap_proc(prc)
49
53
  return unless prc
50
54
 
51
55
  new do |*args|
52
- call_with_argument_mapping(prc, *args)
56
+ begin
57
+ call_with_argument_mapping(prc, *args)
58
+ rescue => e
59
+ GLib::MainLoop.handle_exception e
60
+ end
53
61
  end
54
62
  end
55
63
 
@@ -1,4 +1,5 @@
1
1
  require 'ffi'
2
+ require 'ffi/bit_masks'
2
3
 
3
4
  require 'gir_ffi-base'
4
5
 
@@ -23,6 +23,10 @@ module GirFFI
23
23
  -1
24
24
  end
25
25
 
26
+ def destroy
27
+ -1
28
+ end
29
+
26
30
  def caller_allocates?
27
31
  true
28
32
  end
@@ -0,0 +1,63 @@
1
+ require 'gir_ffi/registered_type_base'
2
+
3
+ module GirFFI
4
+ # Base module for flags.
5
+ module FlagsBase
6
+ include FFI::DataConverter
7
+ include RegisteredTypeBase
8
+
9
+ def native_type
10
+ self::BitMask.native_type
11
+ end
12
+
13
+ def to_native(value, context)
14
+ case value
15
+ when Symbol
16
+ value = { value => true }
17
+ end
18
+ self::BitMask.to_native(value, context)
19
+ end
20
+
21
+ def from_native(*args)
22
+ self::BitMask.from_native(*args).select { |_k, v| v }
23
+ end
24
+
25
+ def [](arg)
26
+ self::BitMask[arg]
27
+ end
28
+
29
+ def wrap(arg)
30
+ self[arg]
31
+ end
32
+
33
+ def from(arg)
34
+ self[arg]
35
+ end
36
+
37
+ def copy_value_to_pointer(value, pointer)
38
+ pointer.put_int32 0, to_native(value, nil)
39
+ end
40
+
41
+ def get_value_from_pointer(pointer, offset)
42
+ from_native pointer.get_int32(offset), nil
43
+ end
44
+
45
+ def setup_and_call(method, arguments, &block)
46
+ result = setup_method method.to_s
47
+
48
+ unless result
49
+ raise "Unable to set up method #{method} in #{self}"
50
+ end
51
+
52
+ send method, *arguments, &block
53
+ end
54
+
55
+ def to_ffi_type
56
+ self
57
+ end
58
+
59
+ def setup_method(name)
60
+ gir_ffi_builder.setup_method name
61
+ end
62
+ end
63
+ end
@@ -47,9 +47,7 @@ module GirFFI
47
47
 
48
48
  class << self
49
49
  def from_closure_data(obj)
50
- FFI::Pointer.new(obj.object_id).tap do |ptr|
51
- ArgHelper::OBJECT_STORE.store(ptr, obj)
52
- end
50
+ ArgHelper::OBJECT_STORE.store(obj)
53
51
  end
54
52
 
55
53
  private
@@ -180,6 +180,12 @@ module GirFFI
180
180
  end
181
181
  end
182
182
 
183
+ GOBJECT_VALUE_NAME = 'GObject::Value'
184
+
185
+ def gvalue?
186
+ argument_class_name == GOBJECT_VALUE_NAME
187
+ end
188
+
183
189
  private
184
190
 
185
191
  def subtype_tag_or_class(index)
@@ -5,6 +5,10 @@ module GirFFI
5
5
  class ObjectBase < ClassBase
6
6
  extend FFI::DataConverter
7
7
 
8
+ def object_class
9
+ self.class.object_class
10
+ end
11
+
8
12
  def self.native_type
9
13
  FFI::Type::POINTER
10
14
  end
@@ -54,7 +58,11 @@ module GirFFI
54
58
  end
55
59
 
56
60
  def self.object_class
57
- gir_ffi_builder.object_class
61
+ @object_class ||=
62
+ begin
63
+ ptr = GObject.type_class_ref(gtype).to_ptr
64
+ gir_ffi_builder.object_class_struct.wrap ptr
65
+ end
58
66
  end
59
67
  end
60
68
  end
@@ -0,0 +1,26 @@
1
+ module GirFFI
2
+ # Helper class for storing objects for later retrieval. Used to store user
3
+ # data arguments.
4
+ class ObjectStore
5
+ def initialize
6
+ @store = {}
7
+ end
8
+
9
+ def store(obj)
10
+ # FIXME: Don't use object_id!
11
+ key = obj.object_id
12
+ @store[key] = obj
13
+ FFI::Pointer.new(key)
14
+ end
15
+
16
+ def fetch(ptr)
17
+ return if ptr.null?
18
+ key = ptr.address
19
+ if @store.key? key
20
+ @store[key]
21
+ else
22
+ ptr
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,31 @@
1
+ require 'gir_ffi/info_ext/full_type_name'
2
+
3
+ module GirFFI
4
+ # Represents a boxed type not found in the GIR, conforming, as needed, to the
5
+ # interface of GObjectIntrospection::IUnionInfo and GObjectIntrospection::IStructInfo.
6
+ class UnintrospectableBoxedInfo
7
+ attr_reader :g_type
8
+
9
+ def initialize(gtype)
10
+ @g_type = gtype
11
+ end
12
+
13
+ def info_type
14
+ :unintrospectable_boxed
15
+ end
16
+
17
+ def safe_name
18
+ GObject.type_name g_type
19
+ end
20
+
21
+ DEFAULT_BOXED_NAMESPACE = 'GLib'
22
+
23
+ def namespace
24
+ DEFAULT_BOXED_NAMESPACE
25
+ end
26
+
27
+ def fields
28
+ []
29
+ end
30
+ end
31
+ end
@@ -47,5 +47,10 @@ module GirFFI
47
47
  def find_signal(_any)
48
48
  nil
49
49
  end
50
+
51
+ # TODO: Create custom class that includes the interfaces instead
52
+ def class_struct
53
+ parent.class_struct
54
+ end
50
55
  end
51
56
  end
@@ -35,10 +35,29 @@ module GirFFI
35
35
  nil
36
36
  end
37
37
 
38
+ def parent_gtype
39
+ @parent_gtype ||= GType.new(@klass.superclass.gtype)
40
+ end
41
+
42
+ def parent
43
+ @parent ||= gir.find_by_gtype(parent_gtype.to_i)
44
+ end
45
+
46
+ # TODO: Create custom class that includes the interfaces instead
47
+ def class_struct
48
+ parent.class_struct
49
+ end
50
+
38
51
  attr_writer :g_name
39
52
 
40
53
  def g_name
41
54
  @g_name ||= @klass.name
42
55
  end
56
+
57
+ private
58
+
59
+ def gir
60
+ @gir ||= GObjectIntrospection::IRepository.default
61
+ end
43
62
  end
44
63
  end
@@ -1,4 +1,4 @@
1
1
  # Current GirFFI version
2
2
  module GirFFI
3
- VERSION = '0.8.6'
3
+ VERSION = '0.9.0'
4
4
  end
@@ -0,0 +1,13 @@
1
+ require 'gir_ffi_test_helper'
2
+
3
+ describe GLib::DestroyNotify do
4
+ describe '.default' do
5
+ it 'removes the passed-in key from the callback store' do
6
+ dummy_proc = 'some-callback'
7
+ GirFFI::CallbackBase.store_callback dummy_proc
8
+ user_data = GirFFI::InPointer.from_closure_data dummy_proc.object_id
9
+ GLib::DestroyNotify.default.call user_data
10
+ GirFFI::CallbackBase::CALLBACKS[dummy_proc.object_id].must_be_nil
11
+ end
12
+ end
13
+ end
@@ -6,9 +6,9 @@ describe GLib::MainLoop do
6
6
  main_loop = GLib::MainLoop.new nil, false
7
7
 
8
8
  a = []
9
- GLib.timeout_add(GLib::PRIORITY_DEFAULT, 150,
10
- proc { main_loop.quit },
11
- nil, nil)
9
+ GLib.timeout_add GLib::PRIORITY_DEFAULT, 150 do
10
+ main_loop.quit
11
+ end
12
12
 
13
13
  slow_thread = Thread.new do
14
14
  sleep 0.001
@@ -18,4 +18,12 @@ describe GObject::ObjectClass do
18
18
  prop_names.sort.must_equal expected_props.sort
19
19
  end
20
20
  end
21
+
22
+ describe '#gtype' do
23
+ it 'returns the correct GType' do
24
+ obj = GIMarshallingTests::OverridesObject.new
25
+ object_class = GObject.object_class_from_instance obj
26
+ object_class.gtype.must_equal GIMarshallingTests::OverridesObject.gtype
27
+ end
28
+ end
21
29
  end
@@ -1,11 +1,25 @@
1
1
  require 'gir_ffi_test_helper'
2
2
 
3
3
  require 'ffi-gobject'
4
+ GirFFI.setup :GIMarshallingTests
4
5
 
5
6
  describe GObject::Object do
6
7
  describe '.new' do
7
8
  it 'is overridden to take only one argument' do
8
- GObject::Object.new(nil).must_be_instance_of GObject::Object
9
+ GObject::Object.new({}).must_be_instance_of GObject::Object
10
+ end
11
+
12
+ it 'can be used to create objects with properties' do
13
+ obj = GIMarshallingTests::SubObject.new(int: 13)
14
+ obj.int.must_equal 13
15
+ end
16
+
17
+ it 'allows omission of the first argument' do
18
+ GObject::Object.new.must_be_instance_of GObject::Object
19
+ end
20
+
21
+ it 'raises an error for properties that do not exist' do
22
+ proc { GObject::Object.new(dog: 'bark') }.must_raise ArgumentError
9
23
  end
10
24
  end
11
25
 
@@ -26,7 +40,7 @@ describe GObject::Object do
26
40
  end
27
41
  end
28
42
 
29
- subject { AccessorTest.new nil }
43
+ subject { AccessorTest.new }
30
44
 
31
45
  it 'reads x by calling get_x' do
32
46
  subject.set_x(1)
@@ -40,7 +54,7 @@ describe GObject::Object do
40
54
  end
41
55
 
42
56
  describe '#signal_connect' do
43
- subject { GObject::Object.new nil }
57
+ subject { GObject::Object.new }
44
58
 
45
59
  it 'delegates to GObject' do
46
60
  expect(GObject).to receive(:signal_connect).with(subject, 'some-event', nil)
@@ -58,7 +72,7 @@ describe GObject::Object do
58
72
  end
59
73
 
60
74
  describe '#signal_connect_after' do
61
- subject { GObject::Object.new nil }
75
+ subject { GObject::Object.new }
62
76
 
63
77
  it 'delegates to GObject' do
64
78
  expect(GObject).to receive(:signal_connect_after).with(subject, 'some-event', nil)
@@ -76,12 +90,16 @@ describe GObject::Object do
76
90
  end
77
91
 
78
92
  describe 'upon garbage collection' do
93
+ # FIXME: Test this some other way
79
94
  it 'lowers the reference count' do
80
95
  if defined?(RUBY_ENGINE) && %w(jruby rbx).include?(RUBY_ENGINE)
81
96
  skip 'cannot be reliably tested on JRuby and Rubinius'
82
97
  end
98
+ if RUBY_VERSION >= '2.3.0'
99
+ skip 'cannot be reliably tested on CRuby >= 2.3'
100
+ end
83
101
 
84
- object = GObject::Object.new nil
102
+ object = GObject::Object.new
85
103
  ptr = object.to_ptr
86
104
  ref_count(ptr).must_equal 1
87
105