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