gir_ffi 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +11 -0
- data/README.rdoc +28 -14
- data/Rakefile +1 -1
- data/TODO.rdoc +3 -24
- data/examples/05_notification.rb +35 -0
- data/lib/gir_ffi/arg_helper.rb +15 -279
- data/lib/gir_ffi/builder/argument/base.rb +110 -0
- data/lib/gir_ffi/builder/argument/hash_table_base.rb +20 -0
- data/lib/gir_ffi/builder/argument/in_base.rb +19 -0
- data/lib/gir_ffi/builder/argument/in_out_base.rb +25 -0
- data/lib/gir_ffi/builder/argument/list_base.rb +16 -0
- data/lib/gir_ffi/builder/argument/out_base.rb +27 -0
- data/lib/gir_ffi/builder/argument.rb +167 -357
- data/lib/gir_ffi/builder/function.rb +2 -0
- data/lib/gir_ffi/builder/module.rb +2 -2
- data/lib/gir_ffi/builder/type/base.rb +7 -0
- data/lib/gir_ffi/builder/type/callback.rb +1 -8
- data/lib/gir_ffi/builder/type/constant.rb +1 -6
- data/lib/gir_ffi/builder/type/enum.rb +2 -7
- data/lib/gir_ffi/builder/type/interface.rb +12 -14
- data/lib/gir_ffi/builder/type/object.rb +32 -13
- data/lib/gir_ffi/builder/type/registered_type.rb +1 -78
- data/lib/gir_ffi/builder/type/struct.rb +2 -0
- data/lib/gir_ffi/builder/type/struct_based.rb +9 -24
- data/lib/gir_ffi/builder/type/unintrospectable.rb +63 -0
- data/lib/gir_ffi/builder/type/union.rb +8 -7
- data/lib/gir_ffi/builder/type/with_layout.rb +43 -0
- data/lib/gir_ffi/builder/type/with_methods.rb +61 -0
- data/lib/gir_ffi/builder.rb +39 -0
- data/lib/gir_ffi/callback_helper.rb +58 -0
- data/lib/gir_ffi/class_base.rb +17 -5
- data/lib/gir_ffi/i_repository.rb +0 -4
- data/lib/gir_ffi/in_out_pointer.rb +76 -0
- data/lib/gir_ffi/in_pointer.rb +46 -0
- data/lib/gir_ffi/interface_base.rb +12 -0
- data/lib/gir_ffi/module_base.rb +7 -3
- data/lib/gir_ffi/overrides/glib.rb +14 -3
- data/lib/gir_ffi/overrides/gobject.rb +37 -15
- data/lib/gir_ffi/overrides/gtk.rb +1 -1
- data/lib/gir_ffi/version.rb +1 -1
- data/lib/gir_ffi.rb +3 -0
- data/tasks/rdoc.rake +6 -0
- data/tasks/test.rake +22 -3
- data/tasks/yardoc.rake +6 -0
- data/test/arg_helper_test.rb +2 -72
- data/test/builder_test.rb +15 -19
- data/test/function_definition_builder_test.rb +30 -37
- data/test/g_object_overrides_test.rb +29 -1
- data/test/glib_overrides_test.rb +4 -0
- data/test/gtk_overrides_test.rb +21 -15
- data/test/i_repository_test.rb +2 -1
- data/test/{generated_gimarshallingtests_test.rb → integration/generated_gimarshallingtests_test.rb} +1 -1
- data/test/integration/generated_gio_test.rb +98 -0
- data/test/integration/generated_gobject_test.rb +30 -0
- data/test/{generated_gtk_test.rb → integration/generated_gtk_test.rb} +5 -5
- data/test/{generated_regress_test.rb → integration/generated_regress_test.rb} +19 -5
- data/test/interface_type_builder_test.rb +1 -1
- data/test/module_builder_test.rb +3 -3
- data/test/test_helper.rb +4 -9
- data/test/type_builder_test.rb +5 -5
- data/test/{dynamic_type_builder_test.rb → unintrospectable_type_builder_test.rb} +12 -8
- data/test/unit/builder_test.rb +31 -0
- data/test/unit/callback_helper_test.rb +19 -0
- data/test/unit/constant_builder_test.rb +5 -0
- data/test/unit/i_constant_info_test.rb +17 -0
- data/test/unit/in_out_pointer_test.rb +118 -0
- data/test/unit/in_pointer_test.rb +69 -0
- data/test/unit/object_type_builder_test.rb +20 -0
- metadata +47 -19
- data/lib/gir_ffi/builder/dynamic_type.rb +0 -41
- data/test/generated_gio_test.rb +0 -39
- data/test/generated_gobject_test.rb +0 -15
- data/test/object_type_builder_test.rb +0 -34
data/History.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 0.0.11 / 2011-08-22
|
2
|
+
|
3
|
+
* Change interface to the underlying builder in generated modules and
|
4
|
+
classes.
|
5
|
+
* Handle string, enum, union, flags signal arguments.
|
6
|
+
* Handle string arguments in GObject.signal_emit.
|
7
|
+
* Handle enum signal arguments.
|
8
|
+
* Fix finding signals in non-introspectable types.
|
9
|
+
* Fix method setup in non-introspectable types.
|
10
|
+
* Refactoring.
|
11
|
+
|
1
12
|
== 0.0.10 / 2011-05-18
|
2
13
|
|
3
14
|
* Handle GObject interfaces properly.
|
data/README.rdoc
CHANGED
@@ -6,12 +6,12 @@ http://www.github.com/mvz/ruby-gir-ffi
|
|
6
6
|
|
7
7
|
== Description
|
8
8
|
|
9
|
-
Ruby
|
9
|
+
Ruby bindings for GNOME using the GObject Introspection Repository.
|
10
10
|
|
11
11
|
== Features/Problems
|
12
12
|
|
13
13
|
* Create bindings to GObject-based libraries at runtime
|
14
|
-
*
|
14
|
+
* Almost, but not entirely done yet
|
15
15
|
|
16
16
|
== Synopsis
|
17
17
|
|
@@ -21,26 +21,40 @@ Ruby-FFI-based binding of the GObject Introspection Repository
|
|
21
21
|
Gtk.init
|
22
22
|
win = Gtk::Window.new :toplevel
|
23
23
|
|
24
|
+
See the `examples/` directory for more, well, examples.
|
25
|
+
|
24
26
|
== Requirements
|
25
27
|
|
26
28
|
* Ruby-FFI of course
|
27
29
|
* gobject-introspection installed with some introspection data
|
28
|
-
* The `rr` and `
|
30
|
+
* The `rr` and `minitest` gems for testing
|
31
|
+
|
32
|
+
Depending on the GIR data, GirFFI needs the actual libraries to be
|
33
|
+
available under the name ending in plain `.so`. If GirFFI complains that it
|
34
|
+
cannot find the library, try installing development packages for those
|
35
|
+
libraries.
|
29
36
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
access. The following set of packages should do the trick:
|
34
|
-
`libgirepository1.0-dev` (at least version 0.10), and either
|
35
|
-
`gir1.2-gtk-3.0` and `libgtk-3-dev`, or `gir1.2-gtk-2.0` and
|
36
|
-
`libgtk2.0-dev`.
|
37
|
+
On Debian and Ubuntu, the following set of packages should be enough to get
|
38
|
+
`rake test` working: `libgirepository1.0-dev` (at least version 0.10),
|
39
|
+
`gir1.2-gtk-2.0` and `libgtk2.0-dev`.
|
37
40
|
|
38
|
-
== Hacking
|
41
|
+
== Hacking and contributing
|
39
42
|
|
40
43
|
This is still very much a work in progress. You can start exploring by
|
41
|
-
running the example programs in the examples
|
42
|
-
works, some are a test bed for how things should work. Have a look at
|
43
|
-
`rake
|
44
|
+
running the example programs in the `examples/` folder. Some illustrate
|
45
|
+
what works, some are a test bed for how things should work. Have a look at
|
46
|
+
the output of `rake notes`. Feel free to file bugs or send pull requests.
|
47
|
+
|
48
|
+
If you want to send pull requests or patches, please:
|
49
|
+
|
50
|
+
* Make sure `rake test` runs without reporting any failures. If your code
|
51
|
+
breaks existing stuff, it won't get merged in.
|
52
|
+
* Add tests for your feature. Otherwise, I can't see if it works or if I
|
53
|
+
break it later.
|
54
|
+
* Make sure latest master merges cleanly with your branch. Things might
|
55
|
+
have moved around since you forked.
|
56
|
+
* Try not to include changes that are irrelevant to your feature in the
|
57
|
+
same commit.
|
44
58
|
|
45
59
|
== Install
|
46
60
|
|
data/Rakefile
CHANGED
data/TODO.rdoc
CHANGED
@@ -1,31 +1,10 @@
|
|
1
1
|
= TODO
|
2
2
|
|
3
|
-
==
|
3
|
+
== Separate bindings to GIRepository from dynamic binding generation.
|
4
4
|
|
5
|
-
|
6
|
-
be possible to hand-code only part of it and use that to generate the rest.
|
7
|
-
This would also integrate that properly with the rest of the GObject type
|
8
|
-
system.
|
5
|
+
== Remove code for passing generic pointers
|
9
6
|
|
10
|
-
|
11
|
-
namespace is not object-oriented: The Info structs are not GObjects, and
|
12
|
-
the methods that act upon them are just functions in the GIRepository
|
13
|
-
namespace. Perhaps some custom method_missing can be implemented to handle
|
14
|
-
this, though.
|
15
|
-
|
16
|
-
== Handle passing of generic pointers
|
17
|
-
|
18
|
-
Many GObject methods take a pointer to 'user data'. This means we should be
|
19
|
-
able to pass any Ruby object. On the other hand, these cases cannot be
|
20
|
-
distinguished, based on the GIR data, from methods that take a pointer to
|
21
|
-
any GObject.
|
22
|
-
|
23
|
-
I'm currently passing the object id as the value of the 'gpointer'. Special
|
24
|
-
overrides 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
|
-
|
28
|
-
Update: generic pointers have been declared 'not introspectable', so
|
7
|
+
Generic pointers have been declared 'not introspectable', so
|
29
8
|
handling them can be removed.
|
30
9
|
|
31
10
|
== Handle fundamental objects that are not GObject.
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# Simple notification example.
|
3
|
+
#
|
4
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
5
|
+
require 'gir_ffi'
|
6
|
+
|
7
|
+
GirFFI.setup :Gtk
|
8
|
+
GirFFI.setup :Notify
|
9
|
+
|
10
|
+
# Both Gtk and Notify need to be init'ed.
|
11
|
+
Gtk.init
|
12
|
+
Notify.init "notification test"
|
13
|
+
|
14
|
+
# Basic set up of the notification.
|
15
|
+
nf = Notify::Notification.new "Hello!", "Hi there.", "gtk-dialog-info"
|
16
|
+
nf.set_timeout 3000
|
17
|
+
nf.set_urgency :critical
|
18
|
+
|
19
|
+
# Show a button 'Test' in the notification, with a callback function.
|
20
|
+
nf.add_action "test", "Test", Proc.new { |obj, action, user_data|
|
21
|
+
puts "Action #{action} clicked."
|
22
|
+
}, nil, nil
|
23
|
+
|
24
|
+
# In this case, we want the program to end once the notification is gone,
|
25
|
+
# but not before.
|
26
|
+
GObject.signal_connect(nf, "closed") {
|
27
|
+
puts "Notification closed."
|
28
|
+
Gtk.main_quit
|
29
|
+
}
|
30
|
+
|
31
|
+
# Show the notification.
|
32
|
+
nf.show
|
33
|
+
|
34
|
+
# Start a main loop to wait for the notification to be closed.
|
35
|
+
Gtk.main
|
data/lib/gir_ffi/arg_helper.rb
CHANGED
@@ -1,30 +1,16 @@
|
|
1
1
|
require 'gir_ffi/allocation_helper'
|
2
|
+
require 'gir_ffi/callback_helper'
|
2
3
|
require 'gir_ffi/builder'
|
3
|
-
require 'gir_ffi/builder/dynamic_type'
|
4
4
|
|
5
5
|
module GirFFI
|
6
6
|
module ArgHelper
|
7
|
+
POINTER_SIZE = FFI.type_size(:pointer)
|
8
|
+
|
7
9
|
SIMPLE_G_TYPES = [
|
8
10
|
:gint8, :gint16, :gint, :gint32, :gint64,
|
9
11
|
:guint8, :guint16, :guint32, :guint64,
|
10
12
|
:gfloat, :gdouble]
|
11
13
|
|
12
|
-
def self.setup_array_to_inptr_handler_for *types
|
13
|
-
types.flatten.each do |type|
|
14
|
-
ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
|
15
|
-
defn =
|
16
|
-
"def self.#{type}_array_to_inptr ary
|
17
|
-
return nil if ary.nil?
|
18
|
-
block = allocate_array_of_type #{ffi_type.inspect}, ary.length
|
19
|
-
block.put_array_of_#{ffi_type} 0, ary
|
20
|
-
end"
|
21
|
-
eval defn
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
setup_array_to_inptr_handler_for SIMPLE_G_TYPES
|
26
|
-
setup_array_to_inptr_handler_for :pointer
|
27
|
-
|
28
14
|
# FIXME: Hideous.
|
29
15
|
def self.object_to_inptr obj
|
30
16
|
return obj.to_ptr if obj.respond_to? :to_ptr
|
@@ -33,164 +19,6 @@ module GirFFI
|
|
33
19
|
FFI::Pointer.new(obj.object_id)
|
34
20
|
end
|
35
21
|
|
36
|
-
def self.typed_array_to_inptr type, ary
|
37
|
-
return nil if ary.nil?
|
38
|
-
return utf8_array_to_inptr ary if type == :utf8
|
39
|
-
block = allocate_array_of_type type, ary.length
|
40
|
-
block.send "put_array_of_#{type}", 0, ary
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.utf8_to_inptr str
|
44
|
-
return nil if str.nil?
|
45
|
-
len = str.bytesize
|
46
|
-
AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0)
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.utf8_array_to_inptr ary
|
50
|
-
return nil if ary.nil?
|
51
|
-
ptr_ary = ary.map {|str| utf8_to_inptr str}
|
52
|
-
ptr_ary << nil
|
53
|
-
typed_array_to_inptr :pointer, ptr_ary
|
54
|
-
end
|
55
|
-
|
56
|
-
# FIXME: :interface is too generic. implement only GValueArray?
|
57
|
-
def self.interface_array_to_inptr ary
|
58
|
-
return nil if ary.nil?
|
59
|
-
raise NotImplementedError
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.interface_pointer_array_to_inptr ary
|
63
|
-
return nil if ary.nil?
|
64
|
-
ptr_ary = ary.map {|ifc| ifc.to_ptr}
|
65
|
-
ptr_ary << nil
|
66
|
-
pointer_array_to_inptr ptr_ary
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.cleanup_ptr ptr
|
70
|
-
LibC.free ptr
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.cleanup_ptr_ptr ptr
|
74
|
-
LibC.free ptr.read_pointer
|
75
|
-
LibC.free ptr
|
76
|
-
end
|
77
|
-
|
78
|
-
# Takes an outptr to a pointer array, and frees all pointers.
|
79
|
-
def self.cleanup_ptr_array_ptr ptr, size
|
80
|
-
block = ptr.read_pointer
|
81
|
-
unless block.null?
|
82
|
-
block.read_array_of_pointer(size).each { |pt| LibC.free pt }
|
83
|
-
LibC.free block
|
84
|
-
end
|
85
|
-
LibC.free ptr
|
86
|
-
end
|
87
|
-
|
88
|
-
def self.setup_type_to_inoutptr_handler_for *types
|
89
|
-
types.flatten.each do |type|
|
90
|
-
ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
|
91
|
-
defn =
|
92
|
-
"def self.#{type}_to_inoutptr val
|
93
|
-
#{type}_pointer.put_#{ffi_type} 0, val
|
94
|
-
end"
|
95
|
-
eval defn
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
setup_type_to_inoutptr_handler_for SIMPLE_G_TYPES
|
100
|
-
setup_type_to_inoutptr_handler_for :pointer
|
101
|
-
|
102
|
-
def self.gboolean_to_inoutptr val
|
103
|
-
gboolean_pointer.put_int 0, (val ? 1 : 0)
|
104
|
-
end
|
105
|
-
|
106
|
-
def self.utf8_to_inoutptr str
|
107
|
-
sptr = utf8_to_inptr str
|
108
|
-
pointer_pointer.write_pointer sptr
|
109
|
-
end
|
110
|
-
|
111
|
-
def self.int32_array_to_inoutptr ary
|
112
|
-
block = gint32_array_to_inptr ary
|
113
|
-
pointer_pointer.write_pointer block
|
114
|
-
end
|
115
|
-
|
116
|
-
def self.utf8_array_to_inoutptr ary
|
117
|
-
return nil if ary.nil?
|
118
|
-
pointer_pointer.write_pointer utf8_array_to_inptr(ary)
|
119
|
-
end
|
120
|
-
|
121
|
-
class << self
|
122
|
-
alias int_array_to_inoutptr int32_array_to_inoutptr
|
123
|
-
alias gint32_array_to_inoutptr int32_array_to_inoutptr
|
124
|
-
end
|
125
|
-
|
126
|
-
def self.setup_pointer_maker_for *types
|
127
|
-
types.flatten.each do |type|
|
128
|
-
ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
|
129
|
-
size = FFI.type_size ffi_type
|
130
|
-
defn =
|
131
|
-
"def self.#{type}_pointer
|
132
|
-
AllocationHelper.safe_malloc #{size}
|
133
|
-
end"
|
134
|
-
eval defn
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
setup_pointer_maker_for SIMPLE_G_TYPES
|
139
|
-
setup_pointer_maker_for :pointer
|
140
|
-
|
141
|
-
class << self
|
142
|
-
alias gboolean_pointer gint_pointer
|
143
|
-
end
|
144
|
-
|
145
|
-
def self.setup_type_outptr_handler_for *types
|
146
|
-
types.flatten.each do |type|
|
147
|
-
ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
|
148
|
-
defn =
|
149
|
-
"def self.#{type}_outptr
|
150
|
-
#{type}_pointer.put_#{ffi_type} 0, 0
|
151
|
-
end"
|
152
|
-
eval defn
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
setup_type_outptr_handler_for SIMPLE_G_TYPES
|
157
|
-
|
158
|
-
def self.gboolean_outptr
|
159
|
-
gboolean_pointer.put_int 0, 0
|
160
|
-
end
|
161
|
-
|
162
|
-
def self.pointer_outptr
|
163
|
-
pointer_pointer.put_pointer 0, nil
|
164
|
-
end
|
165
|
-
|
166
|
-
def self.utf8_outptr
|
167
|
-
pointer_outptr
|
168
|
-
end
|
169
|
-
|
170
|
-
def self.setup_outptr_to_type_handler_for *types
|
171
|
-
types.flatten.each do |type|
|
172
|
-
ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
|
173
|
-
defn =
|
174
|
-
"def self.outptr_to_#{type} ptr
|
175
|
-
ptr.get_#{ffi_type} 0
|
176
|
-
end"
|
177
|
-
eval defn
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
setup_outptr_to_type_handler_for SIMPLE_G_TYPES
|
182
|
-
setup_outptr_to_type_handler_for :pointer
|
183
|
-
|
184
|
-
# Converts an outptr to a boolean.
|
185
|
-
def self.outptr_to_gboolean ptr
|
186
|
-
(ptr.get_int 0) != 0
|
187
|
-
end
|
188
|
-
|
189
|
-
# Converts an outptr to a string.
|
190
|
-
def self.outptr_to_utf8 ptr
|
191
|
-
ptr_to_utf8 ptr.read_pointer
|
192
|
-
end
|
193
|
-
|
194
22
|
# Converts an outptr to a string array.
|
195
23
|
def self.outptr_to_utf8_array ptr, size
|
196
24
|
block = ptr.read_pointer
|
@@ -221,7 +49,8 @@ module GirFFI
|
|
221
49
|
if type == :utf8
|
222
50
|
ptr_to_utf8_array ptr, size
|
223
51
|
else
|
224
|
-
|
52
|
+
ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
|
53
|
+
ptr.send "get_array_of_#{ffi_type}", 0, size
|
225
54
|
end
|
226
55
|
end
|
227
56
|
|
@@ -245,13 +74,10 @@ module GirFFI
|
|
245
74
|
end
|
246
75
|
|
247
76
|
def self.ptr_to_interface_array klass, ptr, size
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
arr << klass.wrap(ptr)
|
252
|
-
ptr += sz
|
77
|
+
struct_size = klass.ffi_structure.size
|
78
|
+
size.times.map do |idx|
|
79
|
+
klass.wrap(ptr + struct_size * idx)
|
253
80
|
end
|
254
|
-
arr
|
255
81
|
end
|
256
82
|
|
257
83
|
if RUBY_VERSION < "1.9"
|
@@ -272,10 +98,6 @@ module GirFFI
|
|
272
98
|
class << self
|
273
99
|
sz = FFI.type_size(:size_t) * 8
|
274
100
|
type = "guint#{sz}"
|
275
|
-
alias_method :gtype_array_to_inptr, "#{type}_array_to_inptr"
|
276
|
-
alias_method :gtype_outptr, "#{type}_outptr"
|
277
|
-
alias_method :gtype_to_inoutptr, "#{type}_to_inoutptr"
|
278
|
-
alias_method :outptr_to_gtype, "outptr_to_#{type}"
|
279
101
|
alias_method :ptr_to_gtype_array, "ptr_to_#{type}_array"
|
280
102
|
end
|
281
103
|
|
@@ -285,13 +107,10 @@ module GirFFI
|
|
285
107
|
|
286
108
|
def self.strv_to_utf8_array strv
|
287
109
|
return [] if strv.null?
|
288
|
-
arr = []
|
289
|
-
|
290
|
-
loop do
|
291
|
-
ptr = strv.get_pointer i * FFI.type_size(:pointer)
|
292
|
-
break if ptr.null?
|
110
|
+
arr, offset = [], 0
|
111
|
+
until (ptr = strv.get_pointer offset).null? do
|
293
112
|
arr << ptr.read_string
|
294
|
-
|
113
|
+
offset += POINTER_SIZE
|
295
114
|
end
|
296
115
|
return arr
|
297
116
|
end
|
@@ -299,7 +118,7 @@ module GirFFI
|
|
299
118
|
def self.utf8_array_to_glist arr
|
300
119
|
return nil if arr.nil?
|
301
120
|
arr.inject(GLib.list_new :utf8) { |lst, str|
|
302
|
-
GLib.list_append lst,
|
121
|
+
GLib.list_append lst, InPointer.from(:utf8, str) }
|
303
122
|
end
|
304
123
|
|
305
124
|
def self.gint32_array_to_glist arr
|
@@ -311,7 +130,7 @@ module GirFFI
|
|
311
130
|
def self.utf8_array_to_gslist arr
|
312
131
|
return nil if arr.nil?
|
313
132
|
arr.reverse.inject(GLib.slist_new :utf8) { |lst, str|
|
314
|
-
GLib.slist_prepend lst,
|
133
|
+
GLib.slist_prepend lst, InPointer.from(:utf8, str) }
|
315
134
|
end
|
316
135
|
|
317
136
|
def self.gint32_array_to_gslist arr
|
@@ -335,80 +154,6 @@ module GirFFI
|
|
335
154
|
raise NotImplementedError
|
336
155
|
end
|
337
156
|
|
338
|
-
def self.glist_to_utf8_array ptr
|
339
|
-
return [] if ptr.null?
|
340
|
-
# FIXME: Quasi-circular dependency on generated module
|
341
|
-
list = GLib::List.wrap(ptr)
|
342
|
-
str = ptr_to_utf8(list[:data])
|
343
|
-
[str] + glist_to_utf8_array(list[:next])
|
344
|
-
end
|
345
|
-
|
346
|
-
def self.gslist_to_utf8_array ptr
|
347
|
-
return [] if ptr.null?
|
348
|
-
# FIXME: Quasi-circular dependency on generated module
|
349
|
-
list = GLib::SList.wrap(ptr)
|
350
|
-
str = ptr_to_utf8(list[:data])
|
351
|
-
[str] + gslist_to_utf8_array(list[:next])
|
352
|
-
end
|
353
|
-
|
354
|
-
def self.outgslist_to_utf8_array ptr
|
355
|
-
gslist_to_utf8_array ptr.read_pointer
|
356
|
-
end
|
357
|
-
|
358
|
-
def self.wrap_in_callback_args_mapper namespace, name, prc
|
359
|
-
return prc if FFI::Function === prc
|
360
|
-
return nil if prc.nil?
|
361
|
-
info = gir.find_by_name namespace, name
|
362
|
-
return Proc.new do |*args|
|
363
|
-
prc.call(*map_callback_args(args, info))
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
def self.map_callback_args args, info
|
368
|
-
args.zip(info.args).map { |arg, inf|
|
369
|
-
map_single_callback_arg arg, inf }
|
370
|
-
end
|
371
|
-
|
372
|
-
# TODO: Use GirFFI::ReturnValue classes for mapping.
|
373
|
-
def self.map_single_callback_arg arg, info
|
374
|
-
case info.argument_type.tag
|
375
|
-
when :interface
|
376
|
-
map_interface_callback_arg arg, info
|
377
|
-
when :utf8
|
378
|
-
ptr_to_utf8 arg
|
379
|
-
when :void
|
380
|
-
map_void_callback_arg arg
|
381
|
-
else
|
382
|
-
arg
|
383
|
-
end
|
384
|
-
end
|
385
|
-
|
386
|
-
def self.map_interface_callback_arg arg, info
|
387
|
-
iface = info.argument_type.interface
|
388
|
-
case iface.info_type
|
389
|
-
when :object
|
390
|
-
object_pointer_to_object arg
|
391
|
-
when :struct
|
392
|
-
klass = GirFFI::Builder.build_class iface
|
393
|
-
klass.wrap arg
|
394
|
-
else
|
395
|
-
arg
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
def self.map_void_callback_arg arg
|
400
|
-
if arg.null?
|
401
|
-
nil
|
402
|
-
else
|
403
|
-
begin
|
404
|
-
# TODO: Use custom object store.
|
405
|
-
ObjectSpace._id2ref arg.address
|
406
|
-
rescue RangeError
|
407
|
-
arg
|
408
|
-
end
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
157
|
def self.check_error errpp
|
413
158
|
errp = errpp.read_pointer
|
414
159
|
raise GError.new(errp)[:message] unless errp.null?
|
@@ -427,20 +172,11 @@ module GirFFI
|
|
427
172
|
# FIXME: Quasi-circular dependency on generated module
|
428
173
|
def self.object_pointer_to_object optr
|
429
174
|
return nil if optr.null?
|
430
|
-
|
431
|
-
|
432
|
-
if info.nil?
|
433
|
-
klass = GirFFI::Builder::DynamicType.new(tp).build_class
|
434
|
-
else
|
435
|
-
klass = GirFFI::Builder.build_class info
|
436
|
-
end
|
175
|
+
gtype = ::GObject.type_from_instance_pointer optr
|
176
|
+
klass = GirFFI::Builder.build_by_gtype gtype
|
437
177
|
klass.wrap optr
|
438
178
|
end
|
439
179
|
|
440
|
-
def self.gir
|
441
|
-
gir = GirFFI::IRepository.default
|
442
|
-
end
|
443
|
-
|
444
180
|
def self.cast_from_pointer type, it
|
445
181
|
case type
|
446
182
|
when :utf8, :filename
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module GirFFI
|
2
|
+
module Builder
|
3
|
+
module Argument
|
4
|
+
# Abstract parent class of the argument building classes. These
|
5
|
+
# classes are used by Builder::Function to create the code that
|
6
|
+
# processes each argument before and after the actual function call.
|
7
|
+
class Base
|
8
|
+
KEYWORDS = [
|
9
|
+
"alias", "and", "begin", "break", "case", "class", "def", "do",
|
10
|
+
"else", "elsif", "end", "ensure", "false", "for", "if", "in",
|
11
|
+
"module", "next", "nil", "not", "or", "redo", "rescue", "retry",
|
12
|
+
"return", "self", "super", "then", "true", "undef", "unless",
|
13
|
+
"until", "when", "while", "yield"
|
14
|
+
]
|
15
|
+
|
16
|
+
attr_reader :callarg, :name, :retname
|
17
|
+
|
18
|
+
attr_accessor :length_arg, :array_arg
|
19
|
+
|
20
|
+
def initialize function_builder, arginfo=nil, libmodule=nil
|
21
|
+
@arginfo = arginfo
|
22
|
+
@inarg = nil
|
23
|
+
@callarg = nil
|
24
|
+
@retname = nil
|
25
|
+
@name = nil
|
26
|
+
@function_builder = function_builder
|
27
|
+
@libmodule = libmodule
|
28
|
+
@length_arg = nil
|
29
|
+
@array_arg = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def prepare; end
|
33
|
+
|
34
|
+
def type_info
|
35
|
+
@arginfo.argument_type
|
36
|
+
end
|
37
|
+
|
38
|
+
def type_tag
|
39
|
+
tag = type_info.tag
|
40
|
+
tag == :GType ? :gtype : tag
|
41
|
+
end
|
42
|
+
|
43
|
+
def subtype_tag index=0
|
44
|
+
st = type_info.param_type(index)
|
45
|
+
t = st.tag
|
46
|
+
case t
|
47
|
+
when :GType
|
48
|
+
return :gtype
|
49
|
+
when :interface
|
50
|
+
return :interface_pointer if st.pointer?
|
51
|
+
return :interface
|
52
|
+
else
|
53
|
+
return t
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def argument_class_name
|
58
|
+
iface = type_info.interface
|
59
|
+
"::#{iface.safe_namespace}::#{iface.name}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def subtype_class_name index=0
|
63
|
+
iface = type_info.param_type(index).interface
|
64
|
+
"::#{iface.safe_namespace}::#{iface.name}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def array_size
|
68
|
+
if @length_arg
|
69
|
+
@length_arg.retname
|
70
|
+
else
|
71
|
+
type_info.array_fixed_size
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def safe name
|
76
|
+
if KEYWORDS.include? name
|
77
|
+
"#{name}_"
|
78
|
+
else
|
79
|
+
name
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def inarg
|
84
|
+
@array_arg.nil? ? @inarg : nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def retval
|
88
|
+
@array_arg.nil? ? @retname : nil
|
89
|
+
end
|
90
|
+
|
91
|
+
def pre
|
92
|
+
[]
|
93
|
+
end
|
94
|
+
|
95
|
+
def post
|
96
|
+
[]
|
97
|
+
end
|
98
|
+
|
99
|
+
def postpost
|
100
|
+
[]
|
101
|
+
end
|
102
|
+
|
103
|
+
def cleanup
|
104
|
+
[]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module GirFFI
|
2
|
+
module Builder
|
3
|
+
module Argument
|
4
|
+
# Module implementing helper methods needed by HashTable arguments.
|
5
|
+
module HashTableBase
|
6
|
+
private
|
7
|
+
|
8
|
+
def key_t
|
9
|
+
subtype_tag(0).inspect
|
10
|
+
end
|
11
|
+
|
12
|
+
def val_t
|
13
|
+
val_t = subtype_tag(1).inspect
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module GirFFI
|
2
|
+
module Builder
|
3
|
+
module Argument
|
4
|
+
# Abstract base class implementing argument processing for arguments
|
5
|
+
# with direction :in.
|
6
|
+
class InBase < Base
|
7
|
+
def prepare
|
8
|
+
@name = safe(@arginfo.name)
|
9
|
+
@inarg = @name
|
10
|
+
end
|
11
|
+
|
12
|
+
def callarg
|
13
|
+
@callarg ||= @function_builder.new_var
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|