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.
- checksums.yaml +4 -4
- data/Changelog.md +18 -0
- data/README.md +3 -4
- data/lib/ffi-glib.rb +1 -0
- data/lib/ffi-glib/container_class_methods.rb +12 -0
- data/lib/ffi-glib/destroy_notify.rb +15 -0
- data/lib/ffi-glib/main_loop.rb +23 -4
- data/lib/ffi-gobject.rb +4 -2
- data/lib/ffi-gobject/object.rb +31 -16
- data/lib/ffi-gobject/object_class.rb +4 -0
- data/lib/ffi-gobject/value.rb +3 -3
- data/lib/ffi-gobject_introspection/i_flags_info.rb +0 -1
- data/lib/gir_ffi-base/gobject/lib.rb +10 -0
- data/lib/gir_ffi/arg_helper.rb +1 -22
- data/lib/gir_ffi/boxed_base.rb +1 -0
- data/lib/gir_ffi/builder.rb +7 -1
- data/lib/gir_ffi/builders/argument_builder.rb +21 -9
- data/lib/gir_ffi/builders/argument_builder_collection.rb +28 -9
- data/lib/gir_ffi/builders/base_argument_builder.rb +36 -12
- data/lib/gir_ffi/builders/base_method_builder.rb +1 -1
- data/lib/gir_ffi/builders/callback_argument_builder.rb +4 -0
- data/lib/gir_ffi/builders/closure_to_pointer_convertor.rb +3 -2
- data/lib/gir_ffi/builders/constructor_builder.rb +1 -1
- data/lib/gir_ffi/builders/enum_builder.rb +4 -4
- data/lib/gir_ffi/builders/error_argument_builder.rb +4 -0
- data/lib/gir_ffi/builders/field_builder.rb +23 -9
- data/lib/gir_ffi/builders/flags_builder.rb +28 -0
- data/lib/gir_ffi/builders/full_c_to_ruby_convertor.rb +18 -0
- data/lib/gir_ffi/builders/module_builder.rb +1 -0
- data/lib/gir_ffi/builders/null_argument_builder.rb +9 -1
- data/lib/gir_ffi/builders/object_builder.rb +7 -4
- data/lib/gir_ffi/builders/property_builder.rb +2 -2
- data/lib/gir_ffi/builders/return_value_builder.rb +4 -4
- data/lib/gir_ffi/builders/struct_builder.rb +10 -2
- data/lib/gir_ffi/builders/type_builder.rb +12 -9
- data/lib/gir_ffi/builders/unintrospectable_boxed_builder.rb +26 -0
- data/lib/gir_ffi/builders/user_defined_builder.rb +2 -2
- data/lib/gir_ffi/builders/with_layout.rb +1 -1
- data/lib/gir_ffi/callback_base.rb +13 -5
- data/lib/gir_ffi/core.rb +1 -0
- data/lib/gir_ffi/error_argument_info.rb +4 -0
- data/lib/gir_ffi/flags_base.rb +63 -0
- data/lib/gir_ffi/in_pointer.rb +1 -3
- data/lib/gir_ffi/info_ext/i_type_info.rb +6 -0
- data/lib/gir_ffi/object_base.rb +9 -1
- data/lib/gir_ffi/object_store.rb +26 -0
- data/lib/gir_ffi/unintrospectable_boxed_info.rb +31 -0
- data/lib/gir_ffi/unintrospectable_type_info.rb +5 -0
- data/lib/gir_ffi/user_defined_type_info.rb +19 -0
- data/lib/gir_ffi/version.rb +1 -1
- data/test/ffi-glib/destroy_notify_test.rb +13 -0
- data/test/ffi-glib/main_loop_test.rb +3 -3
- data/test/ffi-gobject/object_class_test.rb +8 -0
- data/test/ffi-gobject/object_test.rb +23 -5
- data/test/ffi-gobject/value_test.rb +19 -5
- data/test/ffi-gobject_test.rb +2 -2
- data/test/gir_ffi/builders/argument_builder_test.rb +12 -2
- data/test/gir_ffi/builders/constructor_builder_test.rb +4 -4
- data/test/gir_ffi/builders/function_builder_test.rb +46 -3
- data/test/gir_ffi/builders/object_builder_test.rb +25 -0
- data/test/gir_ffi/builders/property_builder_test.rb +4 -4
- data/test/gir_ffi/builders/struct_builder_test.rb +15 -13
- data/test/gir_ffi/builders/unintrospectable_boxed_builder_test.rb +33 -0
- data/test/gir_ffi/builders/unintrospectable_builder_test.rb +6 -0
- data/test/gir_ffi/builders/user_defined_builder_test.rb +7 -1
- data/test/gir_ffi/callback_base_test.rb +12 -2
- data/test/gir_ffi/object_base_test.rb +14 -0
- data/test/integration/callback_exceptions_test.rb +61 -0
- data/test/integration/generated_gimarshallingtests_test.rb +70 -70
- data/test/integration/generated_gio_test.rb +1 -1
- data/test/integration/generated_gobject_test.rb +1 -1
- data/test/integration/generated_gtop_test.rb +5 -1
- data/test/integration/generated_regress_test.rb +83 -102
- data/test/integration/generated_warnlib_test.rb +2 -2
- 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:
|
21
|
-
constant:
|
22
|
-
enum:
|
23
|
-
flags:
|
24
|
-
interface:
|
25
|
-
object:
|
26
|
-
struct:
|
27
|
-
union:
|
28
|
-
|
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
|
-
@
|
38
|
+
@info.parent
|
39
39
|
end
|
40
40
|
|
41
41
|
def parent_gtype
|
42
|
-
@parent_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
|
-
#
|
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
|
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
|
-
|
47
|
+
wrap_proc(prc).tap do |cb|
|
44
48
|
store_callback cb
|
45
49
|
end
|
46
50
|
end
|
47
51
|
|
48
|
-
def self.
|
52
|
+
def self.wrap_proc(prc)
|
49
53
|
return unless prc
|
50
54
|
|
51
55
|
new do |*args|
|
52
|
-
|
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
|
|
data/lib/gir_ffi/core.rb
CHANGED
@@ -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
|
data/lib/gir_ffi/in_pointer.rb
CHANGED
data/lib/gir_ffi/object_base.rb
CHANGED
@@ -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
|
-
|
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
|
@@ -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
|
data/lib/gir_ffi/version.rb
CHANGED
@@ -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
|
10
|
-
|
11
|
-
|
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(
|
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
|
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
|
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
|
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
|
102
|
+
object = GObject::Object.new
|
85
103
|
ptr = object.to_ptr
|
86
104
|
ref_count(ptr).must_equal 1
|
87
105
|
|