gir_ffi 0.0.3 → 0.0.4
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.
- data/DESIGN.rdoc +9 -0
- data/History.txt +11 -0
- data/TODO.rdoc +6 -9
- data/examples/01_empty_window.rb +1 -1
- data/examples/02_hello_world.rb +4 -4
- data/examples/03_upgraded_hello_world.rb +7 -8
- data/lib/gir_ffi.rb +0 -4
- data/lib/gir_ffi/arg_helper.rb +27 -2
- data/lib/gir_ffi/builder.rb +13 -86
- data/lib/gir_ffi/builder_helper.rb +2 -15
- data/lib/gir_ffi/class_base.rb +51 -0
- data/lib/gir_ffi/class_builder.rb +178 -52
- data/lib/gir_ffi/function_definition_builder.rb +46 -9
- data/lib/gir_ffi/g_object.rb +37 -0
- data/lib/gir_ffi/i_arg_info.rb +27 -9
- data/lib/gir_ffi/i_base_info.rb +12 -4
- data/lib/gir_ffi/i_callable_info.rb +15 -5
- data/lib/gir_ffi/i_enum_info.rb +9 -3
- data/lib/gir_ffi/i_field_info.rb +12 -4
- data/lib/gir_ffi/i_function_info.rb +24 -8
- data/lib/gir_ffi/i_object_info.rb +63 -21
- data/lib/gir_ffi/i_registered_type_info.rb +11 -0
- data/lib/gir_ffi/i_repository.rb +2 -2
- data/lib/gir_ffi/i_signal_info.rb +1 -1
- data/lib/gir_ffi/i_struct_info.rb +24 -8
- data/lib/gir_ffi/i_type_info.rb +24 -8
- data/lib/gir_ffi/i_union_info.rb +15 -0
- data/lib/gir_ffi/i_value_info.rb +3 -1
- data/lib/gir_ffi/i_vfunc_info.rb +12 -1
- data/lib/gir_ffi/lib.rb +23 -1
- data/lib/gir_ffi/lib_c.rb +1 -1
- data/lib/gir_ffi/module_base.rb +19 -0
- data/lib/gir_ffi/module_builder.rb +67 -20
- data/lib/gir_ffi/overrides/gobject.rb +174 -0
- data/lib/gir_ffi/overrides/gtk.rb +26 -9
- data/test/builder_test.rb +57 -37
- data/test/{base_test.rb → class_base_test.rb} +3 -3
- data/test/class_builder_test.rb +48 -6
- data/test/everything_test.rb +285 -36
- data/test/function_definition_builder_test.rb +11 -9
- data/test/g_object_test.rb +22 -0
- data/test/gobject_overrides_test.rb +216 -0
- data/test/i_object_info_test.rb +21 -0
- data/test/module_builder_test.rb +54 -0
- data/test/test_helper.rb +6 -4
- metadata +18 -14
- data/lib/gir_ffi/base.rb +0 -25
- data/lib/gir_ffi/constructor_definition_builder.rb +0 -20
- data/lib/gir_ffi/g_type.rb +0 -14
- data/lib/gir_ffi/method_missing_definition_builder.rb +0 -59
- data/test/constructor_definition_builder_test.rb +0 -19
- data/test/g_type_test.rb +0 -22
data/DESIGN.rdoc
CHANGED
@@ -45,6 +45,15 @@ GLib::Instantiable; In standard GObject they are functions.
|
|
45
45
|
Possibly, compatibility enhancing code can be added for these specific
|
46
46
|
exceptions.
|
47
47
|
|
48
|
+
== Reference Counting
|
49
|
+
|
50
|
+
Because we can always make sure GObjects are unref'd when the Ruby object
|
51
|
+
is GC'd, the mechanism of floating references actually gets in the way a
|
52
|
+
bit. Therefore, when floating GObjects are constructed, GirFFI will sink
|
53
|
+
them. All GObjects can then safely be unref'd using a Ruby finalizer.
|
54
|
+
GObjects obtained through other mechanisms than with a constructor will be
|
55
|
+
ref'd once when wrapping them in a ruby object.
|
56
|
+
|
48
57
|
== Bootstrapping Class Design
|
49
58
|
|
50
59
|
The interface to the GObject Introspection Repository itself is also
|
data/History.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 0.0.4 / 2010-12-14
|
2
|
+
|
3
|
+
* Lots of changes to the internals.
|
4
|
+
* Handle out-only arguments.
|
5
|
+
* Make use of callbacks from other namespaces work.
|
6
|
+
* Handle virtual methods where the invoker method has a different name.
|
7
|
+
* Implement usable signal_connect and signal_emit.
|
8
|
+
* Sink floating references when creating a GObject.
|
9
|
+
* Implement Union type.
|
10
|
+
* Many small bug fixes.
|
11
|
+
|
1
12
|
== 0.0.3 / 2010-11-19
|
2
13
|
|
3
14
|
* Update to restore Ruby 1.9 support.
|
data/TODO.rdoc
CHANGED
@@ -20,20 +20,17 @@ able to pass any Ruby object. On the other hand, these cases cannot be
|
|
20
20
|
distinguished, based on the GIR data, from methods that take a pointer to
|
21
21
|
any GObject.
|
22
22
|
|
23
|
-
I'm currently
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
I'm currently passing the object id as the value of the 'gpointer'. Special
|
24
|
+
overrided will have to be used for the cases where the 'gpointer' actually
|
25
|
+
needs to be a GObject. I consider it an omission in GIRepository that these
|
26
|
+
two cases are not distinguished.
|
27
27
|
|
28
28
|
== Compatibility with all implementations.
|
29
29
|
|
30
30
|
Currently, there are the following incompatibilities:
|
31
31
|
|
32
|
-
*
|
33
|
-
|
34
|
-
the layout. This *not* a problem in JRuby.
|
35
|
-
|
36
|
-
* JRuby disables ObjectSpace by default, so using _id2ref is not ideal.
|
32
|
+
* JRuby disables ObjectSpace by default, so using _id2ref for handling the
|
33
|
+
passing of generic pointers is not ideal.
|
37
34
|
|
38
35
|
== See Also
|
39
36
|
|
data/examples/01_empty_window.rb
CHANGED
data/examples/02_hello_world.rb
CHANGED
@@ -11,16 +11,16 @@ GirFFI.setup :Gtk
|
|
11
11
|
Gtk.init
|
12
12
|
|
13
13
|
win = Gtk::Window.new(:toplevel)
|
14
|
-
GObject.
|
14
|
+
GObject.signal_connect win, "delete-event" do
|
15
15
|
puts "delete event occured"
|
16
16
|
true
|
17
|
-
|
17
|
+
end
|
18
18
|
|
19
|
-
GObject.
|
19
|
+
GObject.signal_connect(win, "destroy") { Gtk.main_quit }
|
20
20
|
win.set_border_width 10
|
21
21
|
|
22
22
|
but = Gtk::Button.new_with_label("Hello World")
|
23
|
-
GObject.
|
23
|
+
GObject.signal_connect(but, "clicked") { win.destroy }
|
24
24
|
|
25
25
|
win.add but
|
26
26
|
|
@@ -8,20 +8,19 @@ require 'gir_ffi'
|
|
8
8
|
GirFFI.setup :GObject
|
9
9
|
GirFFI.setup :Gtk
|
10
10
|
|
11
|
-
callback =
|
12
|
-
|
13
|
-
|
14
|
-
}
|
11
|
+
callback = lambda { |widget, data|
|
12
|
+
puts "Hello again - #{data} was pressed"
|
13
|
+
}
|
15
14
|
|
16
15
|
Gtk.init
|
17
16
|
|
18
17
|
win = Gtk::Window.new(:toplevel)
|
19
18
|
win.set_title "Hello Buttons!"
|
20
19
|
|
21
|
-
GObject.
|
20
|
+
GObject.signal_connect win, "delete-event" do
|
22
21
|
Gtk.main_quit
|
23
22
|
false
|
24
|
-
|
23
|
+
end
|
25
24
|
|
26
25
|
win.set_border_width 10
|
27
26
|
|
@@ -29,12 +28,12 @@ box = Gtk::HBox.new(false, 0)
|
|
29
28
|
win.add box
|
30
29
|
|
31
30
|
button = Gtk::Button.new_with_label("Button 1")
|
32
|
-
GObject.
|
31
|
+
GObject.signal_connect button, "clicked", "button 1", &callback
|
33
32
|
box.pack_start button, true, true, 0
|
34
33
|
button.show
|
35
34
|
|
36
35
|
button = Gtk::Button.new_with_label("Button 2")
|
37
|
-
GObject.
|
36
|
+
GObject.signal_connect button, "clicked", "button 2", &callback
|
38
37
|
box.pack_start button, true, true, 0
|
39
38
|
button.show
|
40
39
|
|
data/lib/gir_ffi.rb
CHANGED
data/lib/gir_ffi/arg_helper.rb
CHANGED
@@ -22,14 +22,21 @@ module GirFFI
|
|
22
22
|
AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0)
|
23
23
|
}
|
24
24
|
|
25
|
-
|
25
|
+
ptr_size = FFI.type_size(:pointer)
|
26
|
+
block = AllocationHelper.safe_malloc ptr_size * ptrs.length
|
26
27
|
block.write_array_of_pointer ptrs
|
27
28
|
|
28
|
-
argv = AllocationHelper.safe_malloc
|
29
|
+
argv = AllocationHelper.safe_malloc ptr_size
|
29
30
|
argv.write_pointer block
|
30
31
|
argv
|
31
32
|
end
|
32
33
|
|
34
|
+
def self.double_to_inoutptr val
|
35
|
+
ptr = AllocationHelper.safe_malloc FFI.type_size(:double)
|
36
|
+
ptr.put_double 0, val
|
37
|
+
return ptr
|
38
|
+
end
|
39
|
+
|
33
40
|
# Converts an outptr to an int, then frees the outptr.
|
34
41
|
def self.outptr_to_int ptr
|
35
42
|
value = ptr.read_int
|
@@ -58,6 +65,13 @@ module GirFFI
|
|
58
65
|
end
|
59
66
|
end
|
60
67
|
|
68
|
+
# Converts an outptr to a double, then frees the outptr.
|
69
|
+
def self.outptr_to_double ptr
|
70
|
+
value = ptr.get_double 0
|
71
|
+
LibC.free ptr
|
72
|
+
value
|
73
|
+
end
|
74
|
+
|
61
75
|
def self.mapped_callback_args prc=nil, &block
|
62
76
|
return prc if FFI::Function === prc
|
63
77
|
if prc.nil?
|
@@ -79,5 +93,16 @@ module GirFFI
|
|
79
93
|
prc.call(*mapped)
|
80
94
|
end
|
81
95
|
end
|
96
|
+
|
97
|
+
def self.check_error errpp
|
98
|
+
errp = errpp.read_pointer
|
99
|
+
raise GError.new(errp)[:message] unless errp.null?
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.sink_if_floating gobject
|
103
|
+
if GirFFI::GObject.object_is_floating(gobject)
|
104
|
+
GirFFI::GObject.object_ref_sink(gobject)
|
105
|
+
end
|
106
|
+
end
|
82
107
|
end
|
83
108
|
end
|
data/lib/gir_ffi/builder.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require 'gir_ffi/arg_helper'
|
2
2
|
require 'gir_ffi/function_definition_builder'
|
3
|
-
require 'gir_ffi/
|
4
|
-
require 'gir_ffi/method_missing_definition_builder'
|
5
|
-
require 'gir_ffi/base'
|
3
|
+
require 'gir_ffi/class_base'
|
6
4
|
require 'gir_ffi/class_builder'
|
7
5
|
require 'gir_ffi/module_builder'
|
8
6
|
require 'gir_ffi/builder_helper'
|
@@ -12,6 +10,7 @@ module GirFFI
|
|
12
10
|
# introspection repository. Call its build_module and build_class methods
|
13
11
|
# to create the modules and classes used in your program.
|
14
12
|
module Builder
|
13
|
+
extend BuilderHelper
|
15
14
|
def self.build_class namespace, classname
|
16
15
|
ClassBuilder.new(namespace, classname).generate
|
17
16
|
end
|
@@ -20,81 +19,6 @@ module GirFFI
|
|
20
19
|
ModuleBuilder.new(namespace).generate
|
21
20
|
end
|
22
21
|
|
23
|
-
def self.setup_method namespace, classname, method
|
24
|
-
go = method_introspection_data namespace, classname, method.to_s
|
25
|
-
|
26
|
-
return false if go.nil?
|
27
|
-
return false if go.type != :function
|
28
|
-
|
29
|
-
klass = build_class namespace, classname
|
30
|
-
modul = build_module namespace
|
31
|
-
lib = modul.const_get(:Lib)
|
32
|
-
|
33
|
-
attach_ffi_function lib, go
|
34
|
-
|
35
|
-
meta = (class << klass; self; end)
|
36
|
-
meta.class_eval function_definition(go, lib)
|
37
|
-
|
38
|
-
true
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.setup_function namespace, method
|
42
|
-
go = function_introspection_data namespace, method.to_s
|
43
|
-
|
44
|
-
return false if go.nil?
|
45
|
-
return false if go.type != :function
|
46
|
-
|
47
|
-
modul = build_module namespace
|
48
|
-
lib = modul.const_get(:Lib)
|
49
|
-
|
50
|
-
attach_ffi_function lib, go
|
51
|
-
|
52
|
-
meta = (class << modul; self; end)
|
53
|
-
meta.class_eval function_definition(go, lib)
|
54
|
-
|
55
|
-
true
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.setup_instance_method namespace, classname, method
|
59
|
-
go = method_introspection_data namespace, classname, method.to_s
|
60
|
-
|
61
|
-
return false if go.nil?
|
62
|
-
return false if go.type != :function
|
63
|
-
|
64
|
-
klass = build_class namespace, classname
|
65
|
-
modul = build_module namespace
|
66
|
-
lib = modul.const_get(:Lib)
|
67
|
-
|
68
|
-
attach_ffi_function lib, go
|
69
|
-
|
70
|
-
klass.class_eval "undef #{method}"
|
71
|
-
klass.class_eval function_definition(go, lib)
|
72
|
-
|
73
|
-
true
|
74
|
-
end
|
75
|
-
|
76
|
-
# All methods below will be made private at the end.
|
77
|
-
|
78
|
-
def self.function_definition info, libmodule
|
79
|
-
if info.constructor?
|
80
|
-
fdbuilder = ConstructorDefinitionBuilder.new info, libmodule
|
81
|
-
else
|
82
|
-
fdbuilder = FunctionDefinitionBuilder.new info, libmodule
|
83
|
-
end
|
84
|
-
fdbuilder.generate
|
85
|
-
end
|
86
|
-
|
87
|
-
def self.function_introspection_data namespace, function
|
88
|
-
gir = IRepository.default
|
89
|
-
return gir.find_by_name namespace, function.to_s
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.method_introspection_data namespace, object, method
|
93
|
-
gir = IRepository.default
|
94
|
-
objectinfo = gir.find_by_name namespace, object.to_s
|
95
|
-
return objectinfo.find_method method
|
96
|
-
end
|
97
|
-
|
98
22
|
def self.attach_ffi_function lib, info
|
99
23
|
sym = info.symbol
|
100
24
|
argtypes = ffi_function_argument_types info
|
@@ -103,6 +27,8 @@ module GirFFI
|
|
103
27
|
lib.attach_function sym, argtypes, rt
|
104
28
|
end
|
105
29
|
|
30
|
+
# All methods below will be made private at the end.
|
31
|
+
|
106
32
|
def self.ffi_function_argument_types info
|
107
33
|
types = info.args.map do |a|
|
108
34
|
iarginfo_to_ffitype a
|
@@ -119,11 +45,14 @@ module GirFFI
|
|
119
45
|
end
|
120
46
|
|
121
47
|
def self.itypeinfo_to_ffitype info
|
48
|
+
tag = info.tag
|
49
|
+
|
122
50
|
if info.pointer?
|
123
|
-
return :string if
|
51
|
+
return :string if tag == :utf8
|
124
52
|
return :pointer
|
125
53
|
end
|
126
|
-
|
54
|
+
|
55
|
+
case tag
|
127
56
|
when :interface
|
128
57
|
interface = info.interface
|
129
58
|
case interface.type
|
@@ -139,12 +68,13 @@ module GirFFI
|
|
139
68
|
when :GType
|
140
69
|
return :int32
|
141
70
|
else
|
142
|
-
return
|
71
|
+
return tag
|
143
72
|
end
|
144
73
|
end
|
145
74
|
|
146
75
|
def self.iarginfo_to_ffitype info
|
147
76
|
return :pointer if info.direction == :inout
|
77
|
+
return :pointer if info.direction == :out
|
148
78
|
return itypeinfo_to_ffitype info.type
|
149
79
|
end
|
150
80
|
|
@@ -154,14 +84,11 @@ module GirFFI
|
|
154
84
|
|
155
85
|
sym = interface.name.to_sym
|
156
86
|
|
157
|
-
|
158
|
-
ft = lib.find_type sym rescue nil
|
159
|
-
if ft.nil?
|
87
|
+
optionally_define_constant modul, sym do
|
160
88
|
args = ffi_function_argument_types interface
|
161
89
|
ret = ffi_function_return_type interface
|
162
90
|
lib.callback sym, args, ret
|
163
91
|
end
|
164
|
-
sym
|
165
92
|
end
|
166
93
|
|
167
94
|
# Set up method access.
|
@@ -169,7 +96,7 @@ module GirFFI
|
|
169
96
|
private_class_method m.to_sym
|
170
97
|
end
|
171
98
|
public_class_method :build_module, :build_class
|
172
|
-
public_class_method :setup_method, :setup_function, :setup_instance_method
|
173
99
|
public_class_method :itypeinfo_to_ffitype
|
100
|
+
public_class_method :attach_ffi_function
|
174
101
|
end
|
175
102
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module GirFFI
|
2
2
|
module BuilderHelper
|
3
|
-
def
|
3
|
+
def const_defined_for parent, name
|
4
4
|
if RUBY_VERSION < "1.9"
|
5
5
|
parent.const_defined? name
|
6
6
|
else
|
@@ -8,25 +8,12 @@ module GirFFI
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def optionally_define_constant parent, name
|
12
12
|
unless const_defined_for parent, name
|
13
13
|
parent.const_set name, yield
|
14
14
|
end
|
15
15
|
parent.const_get name
|
16
16
|
end
|
17
17
|
|
18
|
-
def self.get_or_define_module parent, name
|
19
|
-
optionally_define_constant(parent, name) { Module.new }
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.get_or_define_class namespace, name, parent
|
23
|
-
BuilderHelper.optionally_define_constant namespace, name do
|
24
|
-
if parent.nil?
|
25
|
-
klass = Class.new
|
26
|
-
else
|
27
|
-
klass = Class.new parent
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
18
|
end
|
32
19
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
module GirFFI
|
3
|
+
# Base class for all generated classes. Contains code for dealing with
|
4
|
+
# the generated Struct classes.
|
5
|
+
class ClassBase
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :@struct, :[], :[]=, :to_ptr
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
# TODO: Handle NULL pointer.
|
11
|
+
@struct = ffi_structure.new(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def ffi_structure
|
15
|
+
self.class.ffi_structure
|
16
|
+
end
|
17
|
+
|
18
|
+
def gir_ffi_builder
|
19
|
+
self.class.gir_ffi_builder
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing method, *arguments, &block
|
23
|
+
result = gir_ffi_builder.setup_instance_method method.to_s
|
24
|
+
return super unless result
|
25
|
+
self.send method, *arguments, &block
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.method_missing method, *arguments, &block
|
29
|
+
result = gir_ffi_builder.setup_method method.to_s
|
30
|
+
return super unless result
|
31
|
+
self.send method, *arguments, &block
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
def ffi_structure
|
36
|
+
self.const_get(:Struct)
|
37
|
+
end
|
38
|
+
|
39
|
+
def gir_info
|
40
|
+
self.const_get :GIR_INFO
|
41
|
+
end
|
42
|
+
|
43
|
+
def gir_ffi_builder
|
44
|
+
self.const_get :GIR_FFI_BUILDER
|
45
|
+
end
|
46
|
+
|
47
|
+
alias_method :_real_new, :new
|
48
|
+
undef new
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|