gir_ffi 0.0.10 → 0.0.11
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/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
|
+
|