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.
Files changed (73) hide show
  1. data/History.txt +11 -0
  2. data/README.rdoc +28 -14
  3. data/Rakefile +1 -1
  4. data/TODO.rdoc +3 -24
  5. data/examples/05_notification.rb +35 -0
  6. data/lib/gir_ffi/arg_helper.rb +15 -279
  7. data/lib/gir_ffi/builder/argument/base.rb +110 -0
  8. data/lib/gir_ffi/builder/argument/hash_table_base.rb +20 -0
  9. data/lib/gir_ffi/builder/argument/in_base.rb +19 -0
  10. data/lib/gir_ffi/builder/argument/in_out_base.rb +25 -0
  11. data/lib/gir_ffi/builder/argument/list_base.rb +16 -0
  12. data/lib/gir_ffi/builder/argument/out_base.rb +27 -0
  13. data/lib/gir_ffi/builder/argument.rb +167 -357
  14. data/lib/gir_ffi/builder/function.rb +2 -0
  15. data/lib/gir_ffi/builder/module.rb +2 -2
  16. data/lib/gir_ffi/builder/type/base.rb +7 -0
  17. data/lib/gir_ffi/builder/type/callback.rb +1 -8
  18. data/lib/gir_ffi/builder/type/constant.rb +1 -6
  19. data/lib/gir_ffi/builder/type/enum.rb +2 -7
  20. data/lib/gir_ffi/builder/type/interface.rb +12 -14
  21. data/lib/gir_ffi/builder/type/object.rb +32 -13
  22. data/lib/gir_ffi/builder/type/registered_type.rb +1 -78
  23. data/lib/gir_ffi/builder/type/struct.rb +2 -0
  24. data/lib/gir_ffi/builder/type/struct_based.rb +9 -24
  25. data/lib/gir_ffi/builder/type/unintrospectable.rb +63 -0
  26. data/lib/gir_ffi/builder/type/union.rb +8 -7
  27. data/lib/gir_ffi/builder/type/with_layout.rb +43 -0
  28. data/lib/gir_ffi/builder/type/with_methods.rb +61 -0
  29. data/lib/gir_ffi/builder.rb +39 -0
  30. data/lib/gir_ffi/callback_helper.rb +58 -0
  31. data/lib/gir_ffi/class_base.rb +17 -5
  32. data/lib/gir_ffi/i_repository.rb +0 -4
  33. data/lib/gir_ffi/in_out_pointer.rb +76 -0
  34. data/lib/gir_ffi/in_pointer.rb +46 -0
  35. data/lib/gir_ffi/interface_base.rb +12 -0
  36. data/lib/gir_ffi/module_base.rb +7 -3
  37. data/lib/gir_ffi/overrides/glib.rb +14 -3
  38. data/lib/gir_ffi/overrides/gobject.rb +37 -15
  39. data/lib/gir_ffi/overrides/gtk.rb +1 -1
  40. data/lib/gir_ffi/version.rb +1 -1
  41. data/lib/gir_ffi.rb +3 -0
  42. data/tasks/rdoc.rake +6 -0
  43. data/tasks/test.rake +22 -3
  44. data/tasks/yardoc.rake +6 -0
  45. data/test/arg_helper_test.rb +2 -72
  46. data/test/builder_test.rb +15 -19
  47. data/test/function_definition_builder_test.rb +30 -37
  48. data/test/g_object_overrides_test.rb +29 -1
  49. data/test/glib_overrides_test.rb +4 -0
  50. data/test/gtk_overrides_test.rb +21 -15
  51. data/test/i_repository_test.rb +2 -1
  52. data/test/{generated_gimarshallingtests_test.rb → integration/generated_gimarshallingtests_test.rb} +1 -1
  53. data/test/integration/generated_gio_test.rb +98 -0
  54. data/test/integration/generated_gobject_test.rb +30 -0
  55. data/test/{generated_gtk_test.rb → integration/generated_gtk_test.rb} +5 -5
  56. data/test/{generated_regress_test.rb → integration/generated_regress_test.rb} +19 -5
  57. data/test/interface_type_builder_test.rb +1 -1
  58. data/test/module_builder_test.rb +3 -3
  59. data/test/test_helper.rb +4 -9
  60. data/test/type_builder_test.rb +5 -5
  61. data/test/{dynamic_type_builder_test.rb → unintrospectable_type_builder_test.rb} +12 -8
  62. data/test/unit/builder_test.rb +31 -0
  63. data/test/unit/callback_helper_test.rb +19 -0
  64. data/test/unit/constant_builder_test.rb +5 -0
  65. data/test/unit/i_constant_info_test.rb +17 -0
  66. data/test/unit/in_out_pointer_test.rb +118 -0
  67. data/test/unit/in_pointer_test.rb +69 -0
  68. data/test/unit/object_type_builder_test.rb +20 -0
  69. metadata +47 -19
  70. data/lib/gir_ffi/builder/dynamic_type.rb +0 -41
  71. data/test/generated_gio_test.rb +0 -39
  72. data/test/generated_gobject_test.rb +0 -15
  73. 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-FFI-based binding of the GObject Introspection Repository
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
- * Not done yet
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 `shoulda` gems for testing.
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
- The current implementation needs the actual libraries to be available under
31
- the name ending in just `.so`. On Debian and Ubuntu at least, this means
32
- you have to install the -dev packages of any library you may want to
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/ folder. Some illustrate what
42
- works, some are a test bed for how things should work. Have a look at
43
- `rake -T`. Feel free to file bugs or send pull requests.
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
@@ -1,3 +1,3 @@
1
1
  load 'tasks/setup.rb'
2
2
 
3
- task :default => 'test:run'
3
+ task :default => 'test'
data/TODO.rdoc CHANGED
@@ -1,31 +1,10 @@
1
1
  = TODO
2
2
 
3
- == Use GIR to bootstrap the GIRepository namespace
3
+ == Separate bindings to GIRepository from dynamic binding generation.
4
4
 
5
- Currently, all the classes used to read the GIR are hand-coded. It should
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
- Update: This has been tried, but the problem is that the GIRepository
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
@@ -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
- ptr.send "get_array_of_#{type}", 0, size
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
- sz = klass.ffi_structure.size
249
- arr = []
250
- size.times do
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
- i = 0
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
- i += 1
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, utf8_to_inptr(str) }
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, utf8_to_inptr(str) }
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
- tp = ::GObject.type_from_instance_pointer optr
431
- info = gir.find_by_gtype tp
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
+