gir_ffi 0.0.8 → 0.0.9

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.
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