gir_ffi 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|