gir_ffi 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/History.txt +11 -0
  2. data/TODO.rdoc +5 -0
  3. data/examples/01_empty_window.rb +0 -1
  4. data/examples/02_hello_world.rb +0 -1
  5. data/examples/03_upgraded_hello_world.rb +0 -1
  6. data/examples/04_webkit.rb +0 -1
  7. data/lib/gir_ffi/arg_helper.rb +231 -94
  8. data/lib/gir_ffi/builder/argument.rb +372 -46
  9. data/lib/gir_ffi/builder/module.rb +25 -10
  10. data/lib/gir_ffi/builder/type/constant.rb +39 -0
  11. data/lib/gir_ffi/builder/type/enum.rb +15 -5
  12. data/lib/gir_ffi/builder/type/registered_type.rb +25 -6
  13. data/lib/gir_ffi/builder/type/struct.rb +1 -9
  14. data/lib/gir_ffi/builder/type/union.rb +5 -0
  15. data/lib/gir_ffi/builder/type.rb +13 -14
  16. data/lib/gir_ffi/builder.rb +7 -4
  17. data/lib/gir_ffi/builder_helper.rb +4 -3
  18. data/lib/gir_ffi/i_base_info.rb +4 -0
  19. data/lib/gir_ffi/i_constant_info.rb +9 -0
  20. data/lib/gir_ffi/i_registered_type_info.rb +0 -1
  21. data/lib/gir_ffi/i_repository.rb +8 -2
  22. data/lib/gir_ffi/i_type_info.rb +7 -0
  23. data/lib/gir_ffi/lib.rb +41 -3
  24. data/lib/gir_ffi/overrides/glib.rb +188 -4
  25. data/lib/gir_ffi/overrides/gobject.rb +16 -5
  26. data/tasks/test.rake +1 -1
  27. data/test/arg_helper_test.rb +5 -5
  28. data/test/builder_test.rb +64 -41
  29. data/test/class_base_test.rb +1 -1
  30. data/test/function_definition_builder_test.rb +24 -2
  31. data/test/g_object_overrides_test.rb +1 -3
  32. data/test/g_object_test.rb +1 -1
  33. data/test/generated_gimarshallingtests_test.rb +1677 -0
  34. data/test/generated_gio_test.rb +1 -1
  35. data/test/generated_gtk_test.rb +31 -2
  36. data/test/generated_regress_test.rb +278 -54
  37. data/test/girffi_test.rb +20 -5
  38. data/test/glib_overrides_test.rb +81 -0
  39. data/test/gtk_overrides_test.rb +2 -3
  40. data/test/i_object_info_test.rb +1 -1
  41. data/test/i_repository_test.rb +3 -4
  42. data/test/lib/Makefile.am +18 -2
  43. data/test/module_builder_test.rb +1 -1
  44. data/test/test_helper.rb +88 -5
  45. data/test/type_builder_test.rb +7 -10
  46. metadata +16 -13
data/History.txt CHANGED
@@ -1,3 +1,14 @@
1
+ == 0.0.9 / 2011-05-02
2
+
3
+ * More complete support for the basic types.
4
+ * Improved support for GList, GSList, GStrv, and GValue.
5
+ * Add support for GHashTable, GVariant, GByteArray, and GArray.
6
+ * Generate constants.
7
+ * When setting up a module, set up its dependencies as well.
8
+ * Test against the GIMarshallingTests test namespace.
9
+ * Use minitest/spec for testing.
10
+ * Various bug fixes and internal improvements.
11
+
1
12
  == 0.0.8 / 2011-04-08
2
13
 
3
14
  * Generate modules with names starting with a lowercase letter (like
data/TODO.rdoc CHANGED
@@ -28,6 +28,11 @@ two cases are not distinguished.
28
28
  Update: generic pointers have been declared 'not introspectable', so
29
29
  handling them can be removed.
30
30
 
31
+ == Handle fundamental objects that are not GObject.
32
+
33
+ This is a big one. See commit 1e9822c7817062a9b853269b9418fd78782090b5 in
34
+ gobject-introspection, and TestFundamentalObject in Regress.
35
+
31
36
  == Check binding of GObject:
32
37
 
33
38
  (11:37:03 PM) walters: the basic story is that GObject should be manually bound
@@ -6,7 +6,6 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
6
6
  require 'gir_ffi'
7
7
 
8
8
  GirFFI.setup :Gtk, '2.0'
9
- GirFFI.setup :GObject
10
9
 
11
10
  Gtk.init
12
11
  win = Gtk::Window.new :toplevel
@@ -6,7 +6,6 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
6
6
  require 'gir_ffi'
7
7
 
8
8
  GirFFI.setup :Gtk, '2.0'
9
- GirFFI.setup :GObject
10
9
 
11
10
  Gtk.init
12
11
 
@@ -6,7 +6,6 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
6
6
  require 'gir_ffi'
7
7
 
8
8
  GirFFI.setup :Gtk, '2.0'
9
- GirFFI.setup :GObject
10
9
 
11
10
  callback = lambda { |widget, data|
12
11
  puts "Hello again - #{data} was pressed"
@@ -2,7 +2,6 @@
2
2
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
3
  require 'gir_ffi'
4
4
 
5
- GirFFI.setup :Gtk, '2.0'
6
5
  GirFFI.setup :WebKit, '1.0'
7
6
 
8
7
  Gtk.init
@@ -1,36 +1,44 @@
1
1
  require 'gir_ffi/allocation_helper'
2
+ require 'gir_ffi/builder'
2
3
 
3
4
  module GirFFI
4
5
  module ArgHelper
6
+ SIMPLE_G_TYPES = [
7
+ :gint8, :gint16, :gint, :gint32, :gint64,
8
+ :guint8, :guint16, :guint32, :guint64,
9
+ :gfloat, :gdouble]
10
+
11
+ def self.setup_array_to_inptr_handler_for *types
12
+ types.flatten.each do |type|
13
+ ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
14
+ defn =
15
+ "def self.#{type}_array_to_inptr ary
16
+ return nil if ary.nil?
17
+ block = allocate_array_of_type #{ffi_type.inspect}, ary.length
18
+ block.put_array_of_#{ffi_type} 0, ary
19
+ end"
20
+ eval defn
21
+ end
22
+ end
23
+
24
+ setup_array_to_inptr_handler_for SIMPLE_G_TYPES
25
+ setup_array_to_inptr_handler_for :pointer
26
+
5
27
  # FIXME: Hideous.
6
28
  def self.object_to_inptr obj
7
29
  return obj.to_ptr if obj.respond_to? :to_ptr
8
30
  return nil if obj.nil?
31
+ return obj if obj.is_a? FFI::Pointer
9
32
  FFI::Pointer.new(obj.object_id)
10
33
  end
11
34
 
12
35
  def self.typed_array_to_inptr type, ary
13
36
  return nil if ary.nil?
37
+ return utf8_array_to_inptr ary if type == :utf8
14
38
  block = allocate_array_of_type type, ary.length
15
39
  block.send "put_array_of_#{type}", 0, ary
16
40
  end
17
41
 
18
- def self.int32_array_to_inptr ary
19
- typed_array_to_inptr :int32, ary
20
- end
21
-
22
- def self.int16_array_to_inptr ary
23
- typed_array_to_inptr :int16, ary
24
- end
25
-
26
- def self.int64_array_to_inptr ary
27
- typed_array_to_inptr :int64, ary
28
- end
29
-
30
- def self.int8_array_to_inptr ary
31
- typed_array_to_inptr :int8, ary
32
- end
33
-
34
42
  def self.utf8_to_inptr str
35
43
  return nil if str.nil?
36
44
  len = str.bytesize
@@ -44,28 +52,17 @@ module GirFFI
44
52
  typed_array_to_inptr :pointer, ptr_ary
45
53
  end
46
54
 
47
- def self.gtype_array_to_inptr ary
48
- case FFI.type_size(:size_t)
49
- when 4
50
- int32_array_to_inptr ary
51
- when 8
52
- int64_array_to_inptr ary
53
- else
54
- raise RuntimeError, "Unexpected size of :size_t"
55
- end
56
- end
57
-
58
- def self.gvalue_array_to_inptr ary
55
+ # FIXME: :interface is too generic. implement only GValueArray?
56
+ def self.interface_array_to_inptr ary
59
57
  return nil if ary.nil?
60
58
  raise NotImplementedError
61
59
  end
62
60
 
63
- class << self
64
- alias int_array_to_inptr int32_array_to_inptr
65
- alias gint8_array_to_inptr int8_array_to_inptr
66
- alias gint16_array_to_inptr int16_array_to_inptr
67
- alias gint32_array_to_inptr int32_array_to_inptr
68
- alias gint64_array_to_inptr int64_array_to_inptr
61
+ def self.interface_pointer_array_to_inptr ary
62
+ return nil if ary.nil?
63
+ ptr_ary = ary.map {|ifc| ifc.to_ptr}
64
+ ptr_ary << nil
65
+ pointer_array_to_inptr ptr_ary
69
66
  end
70
67
 
71
68
  def self.cleanup_ptr ptr
@@ -87,8 +84,22 @@ module GirFFI
87
84
  LibC.free ptr
88
85
  end
89
86
 
90
- def self.int32_to_inoutptr val
91
- int32_pointer.put_int32 0, val
87
+ def self.setup_type_to_inoutptr_handler_for *types
88
+ types.flatten.each do |type|
89
+ ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
90
+ defn =
91
+ "def self.#{type}_to_inoutptr val
92
+ #{type}_pointer.put_#{ffi_type} 0, val
93
+ end"
94
+ eval defn
95
+ end
96
+ end
97
+
98
+ setup_type_to_inoutptr_handler_for SIMPLE_G_TYPES
99
+ setup_type_to_inoutptr_handler_for :pointer
100
+
101
+ def self.gboolean_to_inoutptr val
102
+ gboolean_pointer.put_int 0, (val ? 1 : 0)
92
103
  end
93
104
 
94
105
  def self.utf8_to_inoutptr str
@@ -97,81 +108,81 @@ module GirFFI
97
108
  end
98
109
 
99
110
  def self.int32_array_to_inoutptr ary
100
- block = int_array_to_inptr ary
111
+ block = gint32_array_to_inptr ary
101
112
  pointer_pointer.write_pointer block
102
113
  end
103
114
 
104
115
  def self.utf8_array_to_inoutptr ary
105
116
  return nil if ary.nil?
106
-
107
- ptrs = ary.map {|str| utf8_to_inptr str}
108
-
109
- block = AllocationHelper.safe_malloc FFI.type_size(:pointer) * ptrs.length
110
- block.write_array_of_pointer ptrs
111
-
112
- pointer_pointer.write_pointer block
113
- end
114
-
115
- def self.double_to_inoutptr val
116
- double_pointer.put_double 0, val
117
+ pointer_pointer.write_pointer utf8_array_to_inptr(ary)
117
118
  end
118
119
 
119
120
  class << self
120
- alias int_to_inoutptr int32_to_inoutptr
121
- alias gint32_to_inoutptr int32_to_inoutptr
122
121
  alias int_array_to_inoutptr int32_array_to_inoutptr
123
122
  alias gint32_array_to_inoutptr int32_array_to_inoutptr
124
- alias gdouble_to_inoutptr double_to_inoutptr
125
123
  end
126
124
 
127
- def self.int32_pointer
128
- AllocationHelper.safe_malloc FFI.type_size(:int32)
129
- end
130
-
131
- def self.double_pointer
132
- AllocationHelper.safe_malloc FFI.type_size(:double)
125
+ def self.setup_pointer_maker_for *types
126
+ types.flatten.each do |type|
127
+ ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
128
+ size = FFI.type_size ffi_type
129
+ defn =
130
+ "def self.#{type}_pointer
131
+ AllocationHelper.safe_malloc #{size}
132
+ end"
133
+ eval defn
134
+ end
133
135
  end
134
136
 
135
- def self.pointer_pointer
136
- AllocationHelper.safe_malloc FFI.type_size(:pointer)
137
- end
137
+ setup_pointer_maker_for SIMPLE_G_TYPES
138
+ setup_pointer_maker_for :pointer
138
139
 
139
140
  class << self
140
- alias int_pointer int32_pointer
141
- alias gint32_pointer int32_pointer
142
- alias gdouble_pointer double_pointer
141
+ alias gboolean_pointer gint_pointer
143
142
  end
144
143
 
145
- def self.int32_outptr
146
- int32_pointer.put_int32 0, 0
144
+ def self.setup_type_outptr_handler_for *types
145
+ types.flatten.each do |type|
146
+ ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
147
+ defn =
148
+ "def self.#{type}_outptr
149
+ #{type}_pointer.put_#{ffi_type} 0, 0
150
+ end"
151
+ eval defn
152
+ end
147
153
  end
148
154
 
149
- def self.double_outptr
150
- double_pointer.write_double 0.0
155
+ setup_type_outptr_handler_for SIMPLE_G_TYPES
156
+
157
+ def self.gboolean_outptr
158
+ gboolean_pointer.put_int 0, 0
151
159
  end
152
160
 
153
161
  def self.pointer_outptr
154
- pointer_pointer.write_pointer nil
162
+ pointer_pointer.put_pointer 0, nil
155
163
  end
156
164
 
157
165
  def self.utf8_outptr
158
166
  pointer_outptr
159
167
  end
160
168
 
161
- class << self
162
- alias int_outptr int32_outptr
163
- alias gint32_outptr int32_outptr
164
- alias gdouble_outptr double_outptr
169
+ def self.setup_outptr_to_type_handler_for *types
170
+ types.flatten.each do |type|
171
+ ffi_type = GirFFI::Builder::TAG_TYPE_MAP[type] || type
172
+ defn =
173
+ "def self.outptr_to_#{type} ptr
174
+ ptr.get_#{ffi_type} 0
175
+ end"
176
+ eval defn
177
+ end
165
178
  end
166
179
 
167
- # Converts an outptr to a pointer.
168
- def self.outptr_to_pointer ptr
169
- ptr.read_pointer
170
- end
180
+ setup_outptr_to_type_handler_for SIMPLE_G_TYPES
181
+ setup_outptr_to_type_handler_for :pointer
171
182
 
172
- # Converts an outptr to an int.
173
- def self.outptr_to_int32 ptr
174
- ptr.get_int32 0
183
+ # Converts an outptr to a boolean.
184
+ def self.outptr_to_gboolean ptr
185
+ (ptr.get_int 0) != 0
175
186
  end
176
187
 
177
188
  # Converts an outptr to a string.
@@ -183,14 +194,7 @@ module GirFFI
183
194
  def self.outptr_to_utf8_array ptr, size
184
195
  block = ptr.read_pointer
185
196
  return nil if block.null?
186
- ptrs = block.read_array_of_pointer(size)
187
-
188
- ptrs.map { |ptr| ptr_to_utf8 ptr }
189
- end
190
-
191
- # Converts an outptr to a double.
192
- def self.outptr_to_double ptr
193
- ptr.get_double 0
197
+ ptr_to_utf8_array block, size
194
198
  end
195
199
 
196
200
  # Converts an outptr to an array of int.
@@ -200,39 +204,144 @@ module GirFFI
200
204
  ptr_to_int32_array block, size
201
205
  end
202
206
 
207
+ # Converts an outptr to an array of the given class.
208
+ def self.outptr_to_interface_array klass, ptr, size
209
+ block = ptr.read_pointer
210
+ return nil if block.null?
211
+ ptr_to_interface_array klass, block, size
212
+ end
213
+
203
214
  class << self
204
- alias outptr_to_int outptr_to_int32
205
215
  alias outptr_to_int_array outptr_to_int32_array
206
- alias outptr_to_gint32 outptr_to_int32
207
216
  alias outptr_to_gint32_array outptr_to_int32_array
208
- alias outptr_to_gdouble outptr_to_double
217
+ end
218
+
219
+ def self.ptr_to_typed_array type, ptr, size
220
+ if type == :utf8
221
+ ptr_to_utf8_array ptr, size
222
+ else
223
+ ptr.send "get_array_of_#{type}", 0, size
224
+ end
209
225
  end
210
226
 
211
227
  def self.ptr_to_int32_array ptr, size
212
228
  ptr.get_array_of_int32(0, size)
213
229
  end
214
230
 
215
- def self.ptr_to_utf8 ptr
216
- ptr.null? ? nil : ptr.read_string
231
+ def self.ptr_to_int16_array ptr, size
232
+ ptr.get_array_of_int16(0, size)
233
+ end
234
+
235
+ def self.ptr_to_utf8_array ptr, size
236
+ ptrs = ptr.read_array_of_pointer(size)
237
+
238
+ ptrs.map { |ptr| ptr_to_utf8 ptr }
239
+ end
240
+
241
+ def self.ptr_to_interface_array klass, ptr, size
242
+ sz = klass.ffi_structure.size
243
+ arr = []
244
+ size.times do
245
+ arr << klass.wrap(ptr)
246
+ ptr += sz
247
+ end
248
+ arr
249
+ end
250
+
251
+ if RUBY_VERSION < "1.9"
252
+ def self.ptr_to_utf8 ptr
253
+ ptr.null? ? nil : ptr.read_string
254
+ end
255
+ else
256
+ def self.ptr_to_utf8 ptr
257
+ ptr.null? ? nil : ptr.read_string.force_encoding("utf-8")
258
+ end
259
+ end
260
+
261
+ def self.ptr_to_utf8_length ptr, len
262
+ ptr.null? ? nil : ptr.read_string(len)
217
263
  end
218
264
 
219
265
  class << self
220
266
  alias ptr_to_int_array ptr_to_int32_array
221
267
  alias ptr_to_gint32_array ptr_to_int32_array
268
+ alias ptr_to_gint16_array ptr_to_int16_array
269
+ end
270
+
271
+ # Set up gtype handlers depending on type size.
272
+ class << self
273
+ case FFI.type_size(:size_t)
274
+ when 4
275
+ alias gtype_array_to_inptr gint32_array_to_inptr
276
+ alias gtype_outptr gint32_outptr
277
+ alias gtype_to_inoutptr gint32_to_inoutptr
278
+ alias outptr_to_gtype outptr_to_gint32
279
+ when 8
280
+ alias gtype_array_to_inptr gint64_array_to_inptr
281
+ alias gtype_outptr gint64_outptr
282
+ alias gtype_to_inoutptr gint64_to_inoutptr
283
+ alias outptr_to_gtype outptr_to_gint64
284
+ else
285
+ raise RuntimeError, "Unexpected size of :size_t"
286
+ end
287
+ end
288
+
289
+ def self.outptr_strv_to_utf8_array ptr
290
+ strv_to_utf8_array ptr.read_pointer
291
+ end
292
+
293
+ def self.strv_to_utf8_array strv
294
+ return [] if strv.null?
295
+ arr = []
296
+ i = 0
297
+ loop do
298
+ ptr = strv.get_pointer i * FFI.type_size(:pointer)
299
+ break if ptr.null?
300
+ arr << ptr.read_string
301
+ i += 1
302
+ end
303
+ return arr
222
304
  end
223
305
 
224
306
  def self.utf8_array_to_glist arr
225
307
  return nil if arr.nil?
226
- arr.inject(nil) { |lst, str|
308
+ arr.inject(GLib.list_new :utf8) { |lst, str|
227
309
  GLib.list_append lst, utf8_to_inptr(str) }
228
310
  end
229
311
 
312
+ def self.gint32_array_to_glist arr
313
+ return nil if arr.nil?
314
+ arr.inject(GLib.list_new :gint32) { |lst, int|
315
+ GLib.list_append lst, cast_int32_to_pointer(int) }
316
+ end
317
+
230
318
  def self.utf8_array_to_gslist arr
231
319
  return nil if arr.nil?
232
- arr.reverse.inject(nil) { |lst, str|
320
+ arr.reverse.inject(GLib.slist_new :utf8) { |lst, str|
233
321
  GLib.slist_prepend lst, utf8_to_inptr(str) }
234
322
  end
235
323
 
324
+ def self.gint32_array_to_gslist arr
325
+ return nil if arr.nil?
326
+ arr.reverse.inject(GLib.slist_new :gint32) { |lst, int|
327
+ GLib.slist_prepend lst, cast_int32_to_pointer(int) }
328
+ end
329
+
330
+ def self.hash_to_ghash keytype, valtype, hash
331
+ return nil if hash.nil?
332
+ ghash = GLib.hash_table_new keytype, valtype
333
+ hash.each do |key, val|
334
+ ghash.insert key, val
335
+ end
336
+ ghash
337
+ end
338
+
339
+ def self.void_array_to_gslist ary
340
+ return nil if ary.nil?
341
+ return ary if ary.is_a? GLib::SList
342
+ raise NotImplementedError
343
+ end
344
+
236
345
  def self.glist_to_utf8_array ptr
237
346
  return [] if ptr.null?
238
347
  # FIXME: Quasi-circular dependency on generated module
@@ -267,6 +376,7 @@ module GirFFI
267
376
  map_single_callback_arg arg, inf }
268
377
  end
269
378
 
379
+ # TODO: Use GirFFI::ReturnValue classes for mapping.
270
380
  def self.map_single_callback_arg arg, info
271
381
  case info.argument_type.tag
272
382
  when :interface
@@ -333,5 +443,32 @@ module GirFFI
333
443
  def self.gir
334
444
  gir = GirFFI::IRepository.default
335
445
  end
446
+
447
+ def self.cast_from_pointer type, it
448
+ case type
449
+ when :utf8, :filename
450
+ ptr_to_utf8 it
451
+ when :gint32
452
+ cast_pointer_to_int32 it
453
+ else
454
+ it.address
455
+ end
456
+ end
457
+
458
+ def self.cast_uint32_to_int32 val
459
+ if val >= 0x80000000
460
+ -(0x100000000-val)
461
+ else
462
+ val
463
+ end
464
+ end
465
+
466
+ def self.cast_pointer_to_int32 ptr
467
+ cast_uint32_to_int32(ptr.address & 0xffffffff)
468
+ end
469
+
470
+ def self.cast_int32_to_pointer int
471
+ FFI::Pointer.new(int)
472
+ end
336
473
  end
337
474
  end