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
@@ -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