ruby-vips 2.0.13 → 2.1.0

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
  3. data/.github/workflows/test.yml +80 -0
  4. data/.standard.yml +17 -0
  5. data/.yardopts +0 -1
  6. data/CHANGELOG.md +44 -0
  7. data/Gemfile +3 -1
  8. data/README.md +45 -47
  9. data/Rakefile +13 -15
  10. data/TODO +19 -10
  11. data/VERSION +1 -1
  12. data/example/annotate.rb +7 -7
  13. data/example/connection.rb +26 -0
  14. data/example/daltonize8.rb +27 -29
  15. data/example/draw_lines.rb +30 -0
  16. data/example/example1.rb +5 -6
  17. data/example/example2.rb +11 -11
  18. data/example/example3.rb +9 -9
  19. data/example/example4.rb +8 -8
  20. data/example/example5.rb +8 -9
  21. data/example/inheritance_with_refcount.rb +203 -221
  22. data/example/progress.rb +30 -0
  23. data/example/thumb.rb +12 -14
  24. data/example/trim8.rb +7 -7
  25. data/example/watermark.rb +15 -36
  26. data/example/wobble.rb +25 -25
  27. data/lib/ruby-vips.rb +1 -1
  28. data/lib/vips.rb +473 -338
  29. data/lib/vips/access.rb +9 -9
  30. data/lib/vips/align.rb +7 -8
  31. data/lib/vips/angle.rb +8 -9
  32. data/lib/vips/angle45.rb +12 -13
  33. data/lib/vips/bandformat.rb +16 -18
  34. data/lib/vips/blend_mode.rb +36 -0
  35. data/lib/vips/coding.rb +11 -12
  36. data/lib/vips/compass_direction.rb +13 -14
  37. data/lib/vips/connection.rb +46 -0
  38. data/lib/vips/direction.rb +7 -8
  39. data/lib/vips/extend.rb +13 -14
  40. data/lib/vips/gobject.rb +111 -100
  41. data/lib/vips/gvalue.rb +243 -237
  42. data/lib/vips/image.rb +1501 -1338
  43. data/lib/vips/interesting.rb +10 -11
  44. data/lib/vips/interpolate.rb +50 -54
  45. data/lib/vips/interpretation.rb +25 -26
  46. data/lib/vips/kernel.rb +18 -19
  47. data/lib/vips/methods.rb +929 -309
  48. data/lib/vips/mutableimage.rb +154 -0
  49. data/lib/vips/object.rb +318 -208
  50. data/lib/vips/operation.rb +467 -320
  51. data/lib/vips/operationboolean.rb +10 -11
  52. data/lib/vips/operationcomplex.rb +8 -9
  53. data/lib/vips/operationcomplex2.rb +6 -7
  54. data/lib/vips/operationcomplexget.rb +7 -8
  55. data/lib/vips/operationmath.rb +14 -15
  56. data/lib/vips/operationmath2.rb +6 -7
  57. data/lib/vips/operationrelational.rb +11 -12
  58. data/lib/vips/operationround.rb +7 -8
  59. data/lib/vips/region.rb +73 -0
  60. data/lib/vips/size.rb +9 -10
  61. data/lib/vips/source.rb +88 -0
  62. data/lib/vips/sourcecustom.rb +89 -0
  63. data/lib/vips/target.rb +86 -0
  64. data/lib/vips/targetcustom.rb +77 -0
  65. data/lib/vips/version.rb +1 -2
  66. data/ruby-vips.gemspec +29 -20
  67. metadata +51 -40
  68. data/.travis.yml +0 -55
  69. data/install-vips.sh +0 -26
data/lib/vips/gvalue.rb CHANGED
@@ -3,279 +3,285 @@
3
3
  # Author:: John Cupitt (mailto:jcupitt@gmail.com)
4
4
  # License:: MIT
5
5
 
6
- require 'ffi'
6
+ require "ffi"
7
7
 
8
8
  module GObject
9
-
10
- # Represent a GValue. Example use:
11
- #
12
- # ```ruby
13
- # gvalue = GValue::alloc
14
- # gvalue.init GObject::GDOUBLE_TYPE
15
- # gvalue.set 3.1415
16
- # value = gvalue.get
17
- # ```
18
- #
19
- # Lifetime is managed automatically. It doesn't know about all GType values,
20
- # but it does know the ones that libvips uses.
21
-
22
- class GValue < FFI::ManagedStruct
23
- layout :gtype, :GType,
24
- :data, [:ulong_long, 2]
25
-
26
- # convert an enum value (str/symb/int) into an int ready for libvips
27
- def self.from_nick(gtype, value)
28
- value = value.to_s if value.is_a? Symbol
29
-
30
- if value.is_a? String
31
- value = Vips::vips_enum_from_nick "ruby-vips", gtype, value
32
- if value == -1
33
- raise Vips::Error
34
- end
35
- end
36
-
37
- value
9
+ # Represent a GValue. Example use:
10
+ #
11
+ # ```ruby
12
+ # gvalue = GValue::alloc
13
+ # gvalue.init GObject::GDOUBLE_TYPE
14
+ # gvalue.set 3.1415
15
+ # value = gvalue.get
16
+ # # optional -- drop any ref the gvalue had
17
+ # gvalue.unset
18
+ # ```
19
+ #
20
+ # Lifetime is managed automatically. It doesn't know about all GType values,
21
+ # but it does know the ones that libvips uses.
22
+
23
+ class GValue < FFI::ManagedStruct
24
+ layout :gtype, :GType,
25
+ :data, [:ulong_long, 2]
26
+
27
+ # convert an enum value (str/symb/int) into an int ready for libvips
28
+ def self.from_nick(gtype, value)
29
+ value = value.to_s if value.is_a? Symbol
30
+
31
+ if value.is_a? String
32
+ # libvips expects "-" as a separator in enum names, but "_" is more
33
+ # convenient for ruby, eg. :b_w
34
+ value = Vips.vips_enum_from_nick "ruby-vips", gtype, value.tr("_", "-")
35
+ if value == -1
36
+ raise Vips::Error
38
37
  end
38
+ end
39
39
 
40
- # convert an int enum back into a symbol
41
- def self.to_nick(gtype, enum_value)
42
- enum_name = Vips::vips_enum_nick gtype, enum_value
43
- if enum_name == nil
44
- raise Vips::Error
45
- end
40
+ value
41
+ end
46
42
 
47
- enum_name.to_sym
48
- end
43
+ # convert an int enum back into a symbol
44
+ def self.to_nick(gtype, enum_value)
45
+ enum_name = Vips.vips_enum_nick gtype, enum_value
46
+ if enum_name.nil?
47
+ raise Vips::Error
48
+ end
49
49
 
50
- def self.release ptr
51
- # GLib::logger.debug("GObject::GValue::release") {"ptr = #{ptr}"}
52
- ::GObject::g_value_unset ptr
53
- end
50
+ enum_name.to_sym
51
+ end
54
52
 
55
- # Allocate memory for a GValue and return a class wrapper. Memory will
56
- # be freed automatically when it goes out of scope. The GValue is inited
57
- # to 0, use {GValue.init} to set a type.
58
- #
59
- # @return [GValue] a new gvalue set to 0
60
- def self.alloc
61
- # allocate memory
62
- memory = FFI::MemoryPointer.new GValue
63
-
64
- # make this alloc autorelease ... we mustn't release in
65
- # GValue::release, since we are used to wrap GValue pointers
66
- # made by other people
67
- pointer = FFI::Pointer.new GValue, memory
68
-
69
- # ... and wrap in a GValue
70
- return GValue.new pointer
71
- end
53
+ def self.release ptr
54
+ # GLib::logger.debug("GObject::GValue::release") {"ptr = #{ptr}"}
55
+ ::GObject.g_value_unset ptr
56
+ end
72
57
 
73
- # Set the type of thing a gvalue can hold.
74
- #
75
- # @param gtype [GType] the type of thing this GValue can hold.
76
- def init gtype
77
- ::GObject::g_value_init self, gtype
78
- end
58
+ # Allocate memory for a GValue and return a class wrapper. Memory will
59
+ # be freed automatically when it goes out of scope. The GValue is inited
60
+ # to 0, use {GValue.init} to set a type.
61
+ #
62
+ # @return [GValue] a new gvalue set to 0
63
+ def self.alloc
64
+ # allocate memory
65
+ memory = FFI::MemoryPointer.new GValue
66
+
67
+ # make this alloc autorelease ... we mustn't release in
68
+ # GValue::release, since we are used to wrap GValue pointers
69
+ # made by other people
70
+ pointer = FFI::Pointer.new GValue, memory
71
+
72
+ # ... and wrap in a GValue
73
+ GValue.new pointer
74
+ end
79
75
 
80
- # Set the value of a GValue. The value is converted to the type of the
81
- # GValue, if possible.
82
- #
83
- # @param value [Any] The value to set
84
- def set value
85
- # GLib::logger.debug("GObject::GValue.set") {
86
- # "value = #{value.inspect[0..50]}"
87
- # }
76
+ # Set the type of thing a gvalue can hold.
77
+ #
78
+ # @param gtype [GType] the type of thing this GValue can hold.
79
+ def init gtype
80
+ ::GObject.g_value_init self, gtype
81
+ end
88
82
 
89
- gtype = self[:gtype]
90
- fundamental = ::GObject::g_type_fundamental gtype
83
+ # Set the value of a GValue. The value is converted to the type of the
84
+ # GValue, if possible.
85
+ #
86
+ # @param value [Any] The value to set
87
+ def set value
88
+ # GLib::logger.debug("GObject::GValue.set") {
89
+ # "value = #{value.inspect[0..50]}"
90
+ # }
91
91
 
92
- case gtype
93
- when GBOOL_TYPE
94
- ::GObject::g_value_set_boolean self, (value ? 1 : 0)
92
+ gtype = self[:gtype]
93
+ fundamental = ::GObject.g_type_fundamental gtype
95
94
 
96
- when GINT_TYPE
97
- ::GObject::g_value_set_int self, value
95
+ case gtype
96
+ when GBOOL_TYPE
97
+ ::GObject.g_value_set_boolean self, (value ? 1 : 0)
98
98
 
99
- when GUINT64_TYPE
100
- ::GObject::g_value_set_uint64 self, value
99
+ when GINT_TYPE
100
+ ::GObject.g_value_set_int self, value
101
101
 
102
- when GDOUBLE_TYPE
103
- ::GObject::g_value_set_double self, value
102
+ when GUINT64_TYPE
103
+ ::GObject.g_value_set_uint64 self, value
104
104
 
105
- when GSTR_TYPE
106
- ::GObject::g_value_set_string self, value
105
+ when GDOUBLE_TYPE
106
+ ::GObject.g_value_set_double self, value
107
107
 
108
- when Vips::REFSTR_TYPE
109
- ::Vips::vips_value_set_ref_string self, value
108
+ when GSTR_TYPE
109
+ ::GObject.g_value_set_string self, value
110
110
 
111
- when Vips::ARRAY_INT_TYPE
112
- value = [value] unless value.is_a? Array
111
+ when Vips::REFSTR_TYPE
112
+ ::Vips.vips_value_set_ref_string self, value
113
113
 
114
- Vips::vips_value_set_array_int self, nil, value.length
115
- ptr = Vips::vips_value_get_array_int self, nil
116
- ptr.write_array_of_int32 value
114
+ when Vips::ARRAY_INT_TYPE
115
+ value = [value] unless value.is_a? Array
117
116
 
118
- when Vips::ARRAY_DOUBLE_TYPE
119
- value = [value] unless value.is_a? Array
117
+ Vips.vips_value_set_array_int self, nil, value.length
118
+ ptr = Vips.vips_value_get_array_int self, nil
119
+ ptr.write_array_of_int32 value
120
120
 
121
- # this will allocate an array in the gvalue
122
- Vips::vips_value_set_array_double self, nil, value.length
121
+ when Vips::ARRAY_DOUBLE_TYPE
122
+ value = [value] unless value.is_a? Array
123
123
 
124
- # pull the array out and fill it
125
- ptr = Vips::vips_value_get_array_double self, nil
124
+ # this will allocate an array in the gvalue
125
+ Vips.vips_value_set_array_double self, nil, value.length
126
126
 
127
- ptr.write_array_of_double value
127
+ # pull the array out and fill it
128
+ ptr = Vips.vips_value_get_array_double self, nil
128
129
 
129
- when Vips::ARRAY_IMAGE_TYPE
130
- value = [value] unless value.is_a? Array
130
+ ptr.write_array_of_double value
131
131
 
132
- Vips::vips_value_set_array_image self, value.length
133
- ptr = Vips::vips_value_get_array_image self, nil
134
- ptr.write_array_of_pointer value
132
+ when Vips::ARRAY_IMAGE_TYPE
133
+ value = [value] unless value.is_a? Array
135
134
 
136
- # the gvalue needs a ref on each of the images
137
- value.each {|image| ::GObject::g_object_ref image}
135
+ Vips.vips_value_set_array_image self, value.length
136
+ ptr = Vips.vips_value_get_array_image self, nil
137
+ ptr.write_array_of_pointer value
138
138
 
139
- when Vips::BLOB_TYPE
140
- len = value.bytesize
141
- ptr = GLib::g_malloc len
142
- Vips::vips_value_set_blob self, GLib::G_FREE, ptr, len
143
- ptr.write_bytes value
139
+ # the gvalue needs a ref on each of the images
140
+ value.each { |image| ::GObject.g_object_ref image }
144
141
 
145
- else
146
- case fundamental
147
- when GFLAGS_TYPE
148
- ::GObject::g_value_set_flags self, value
142
+ when Vips::BLOB_TYPE
143
+ len = value.bytesize
144
+ ptr = GLib.g_malloc len
145
+ Vips.vips_value_set_blob self, GLib::G_FREE, ptr, len
146
+ ptr.write_bytes value
149
147
 
150
- when GENUM_TYPE
151
- enum_value = GValue.from_nick(self[:gtype], value)
152
- ::GObject::g_value_set_enum self, enum_value
148
+ else
149
+ case fundamental
150
+ when GFLAGS_TYPE
151
+ ::GObject.g_value_set_flags self, value
153
152
 
154
- when GOBJECT_TYPE
155
- ::GObject::g_value_set_object self, value
153
+ when GENUM_TYPE
154
+ enum_value = GValue.from_nick(self[:gtype], value)
155
+ ::GObject.g_value_set_enum self, enum_value
156
156
 
157
- else
158
- raise Vips::Error, "unimplemented gtype for set: " +
159
- "#{::GObject::g_type_name gtype} (#{gtype})"
157
+ when GOBJECT_TYPE
158
+ ::GObject.g_value_set_object self, value
160
159
 
161
- end
162
- end
160
+ else
161
+ raise Vips::Error, "unimplemented gtype for set: " \
162
+ "#{::GObject.g_type_name gtype} (#{gtype})"
163
163
  end
164
+ end
165
+ end
164
166
 
165
- # Get the value of a GValue. The value is converted to a Ruby type in
166
- # the obvious way.
167
- #
168
- # @return [Any] the value held by the GValue
169
- def get
170
- gtype = self[:gtype]
171
- fundamental = ::GObject::g_type_fundamental gtype
172
- result = nil
173
-
174
- case gtype
175
- when GBOOL_TYPE
176
- result = ::GObject::g_value_get_boolean(self) != 0 ? true : false
177
-
178
- when GINT_TYPE
179
- result = ::GObject::g_value_get_int self
180
-
181
- when GUINT64_TYPE
182
- result = ::GObject::g_value_get_uint64 self
183
-
184
- when GDOUBLE_TYPE
185
- result = ::GObject::g_value_get_double self
186
-
187
- when GSTR_TYPE
188
- result = ::GObject::g_value_get_string self
189
-
190
- when Vips::REFSTR_TYPE
191
- len = Vips::SizeStruct.new
192
- result = ::Vips::vips_value_get_ref_string self, len
193
-
194
- when Vips::ARRAY_INT_TYPE
195
- len = Vips::IntStruct.new
196
- array = Vips::vips_value_get_array_int self, len
197
- result = array.get_array_of_int32 0, len[:value]
198
-
199
- when Vips::ARRAY_DOUBLE_TYPE
200
- len = Vips::IntStruct.new
201
- array = Vips::vips_value_get_array_double self, len
202
- result = array.get_array_of_double 0, len[:value]
203
-
204
- when Vips::ARRAY_IMAGE_TYPE
205
- len = Vips::IntStruct.new
206
- array = Vips::vips_value_get_array_image self, len
207
- result = array.get_array_of_pointer 0, len[:value]
208
- result.map! do |pointer|
209
- ::GObject::g_object_ref pointer
210
- Vips::Image.new pointer
211
- end
212
-
213
- when Vips::BLOB_TYPE
214
- len = Vips::SizeStruct.new
215
- array = Vips::vips_value_get_blob self, len
216
- result = array.get_bytes 0, len[:value]
217
-
218
- else
219
- case fundamental
220
- when GFLAGS_TYPE
221
- result = ::GObject::g_value_get_flags self
222
-
223
- when GENUM_TYPE
224
- enum_value = ::GObject::g_value_get_enum(self)
225
- result = GValue.to_nick self[:gtype], enum_value
226
-
227
- when GOBJECT_TYPE
228
- obj = ::GObject::g_value_get_object self
229
- # g_value_get_object() does not add a ref ... we need to add
230
- # one to match the unref in gobject release
231
- ::GObject::g_object_ref obj
232
- result = Vips::Image.new obj
233
-
234
- else
235
- raise Vips::Error, "unimplemented gtype for get: " +
236
- "#{::GObject::g_type_name gtype} (#{gtype})"
237
-
238
- end
239
- end
240
-
241
- # GLib::logger.debug("GObject::GValue.get") {
242
- # "result = #{result.inspect[0..50]}"
243
- # }
244
-
245
- return result
167
+ # Get the value of a GValue. The value is converted to a Ruby type in
168
+ # the obvious way.
169
+ #
170
+ # @return [Any] the value held by the GValue
171
+ def get
172
+ gtype = self[:gtype]
173
+ fundamental = ::GObject.g_type_fundamental gtype
174
+ result = nil
175
+
176
+ case gtype
177
+ when GBOOL_TYPE
178
+ result = ::GObject.g_value_get_boolean(self) != 0
179
+
180
+ when GINT_TYPE
181
+ result = ::GObject.g_value_get_int self
182
+
183
+ when GUINT64_TYPE
184
+ result = ::GObject.g_value_get_uint64 self
185
+
186
+ when GDOUBLE_TYPE
187
+ result = ::GObject.g_value_get_double self
188
+
189
+ when GSTR_TYPE
190
+ result = ::GObject.g_value_get_string self
191
+
192
+ when Vips::REFSTR_TYPE
193
+ len = Vips::SizeStruct.new
194
+ result = ::Vips.vips_value_get_ref_string self, len
195
+
196
+ when Vips::ARRAY_INT_TYPE
197
+ len = Vips::IntStruct.new
198
+ array = Vips.vips_value_get_array_int self, len
199
+ result = array.get_array_of_int32 0, len[:value]
200
+
201
+ when Vips::ARRAY_DOUBLE_TYPE
202
+ len = Vips::IntStruct.new
203
+ array = Vips.vips_value_get_array_double self, len
204
+ result = array.get_array_of_double 0, len[:value]
205
+
206
+ when Vips::ARRAY_IMAGE_TYPE
207
+ len = Vips::IntStruct.new
208
+ array = Vips.vips_value_get_array_image self, len
209
+ result = array.get_array_of_pointer 0, len[:value]
210
+ result.map! do |pointer|
211
+ ::GObject.g_object_ref pointer
212
+ Vips::Image.new pointer
213
+ end
246
214
 
215
+ when Vips::BLOB_TYPE
216
+ len = Vips::SizeStruct.new
217
+ array = Vips.vips_value_get_blob self, len
218
+ result = array.get_bytes 0, len[:value]
219
+
220
+ else
221
+ case fundamental
222
+ when GFLAGS_TYPE
223
+ result = ::GObject.g_value_get_flags self
224
+
225
+ when GENUM_TYPE
226
+ enum_value = ::GObject.g_value_get_enum(self)
227
+ result = GValue.to_nick self[:gtype], enum_value
228
+
229
+ when GOBJECT_TYPE
230
+ obj = ::GObject.g_value_get_object self
231
+ # g_value_get_object() does not add a ref ... we need to add
232
+ # one to match the unref in gobject release
233
+ ::GObject.g_object_ref obj
234
+ result = Vips::Image.new obj
235
+
236
+ else
237
+ raise Vips::Error, "unimplemented gtype for get: " \
238
+ "#{::GObject.g_type_name gtype} (#{gtype})"
247
239
  end
240
+ end
248
241
 
249
- end
242
+ # GLib::logger.debug("GObject::GValue.get") {
243
+ # "result = #{result.inspect[0..50]}"
244
+ # }
250
245
 
251
- attach_function :g_value_init, [GValue.ptr, :GType], :void
252
-
253
- # we must use a plain :pointer here, since we call this from #release, which
254
- # just gives us the unwrapped pointer, not the ruby class
255
- attach_function :g_value_unset, [:pointer], :void
256
-
257
- attach_function :g_value_set_boolean, [GValue.ptr, :int], :void
258
- attach_function :g_value_set_int, [GValue.ptr, :int], :void
259
- attach_function :g_value_set_uint64, [GValue.ptr, :uint64], :void
260
- attach_function :g_value_set_double, [GValue.ptr, :double], :void
261
- attach_function :g_value_set_enum, [GValue.ptr, :int], :void
262
- attach_function :g_value_set_flags, [GValue.ptr, :uint], :void
263
- attach_function :g_value_set_string, [GValue.ptr, :string], :void
264
- attach_function :g_value_set_object, [GValue.ptr, :pointer], :void
265
-
266
- attach_function :g_value_get_boolean, [GValue.ptr], :int
267
- attach_function :g_value_get_int, [GValue.ptr], :int
268
- attach_function :g_value_get_uint64, [GValue.ptr], :uint64
269
- attach_function :g_value_get_double, [GValue.ptr], :double
270
- attach_function :g_value_get_enum, [GValue.ptr], :int
271
- attach_function :g_value_get_flags, [GValue.ptr], :int
272
- attach_function :g_value_get_string, [GValue.ptr], :string
273
- attach_function :g_value_get_object, [GValue.ptr], :pointer
274
-
275
- # use :pointer rather than GObject.ptr to avoid casting later
276
- attach_function :g_object_set_property,
277
- [:pointer, :string, GValue.ptr], :void
278
- attach_function :g_object_get_property,
279
- [:pointer, :string, GValue.ptr], :void
246
+ result
247
+ end
280
248
 
249
+ # Clear the thing held by a GValue.
250
+ #
251
+ # This happens automatically when a GValue is GCed, but this method can be
252
+ # handy if you need to drop a reference explicitly for some reason.
253
+ def unset
254
+ ::GObject.g_value_unset self
255
+ end
256
+ end
257
+
258
+ attach_function :g_value_init, [GValue.ptr, :GType], :void
259
+
260
+ # we must use a plain :pointer here, since we call this from #release, which
261
+ # just gives us the unwrapped pointer, not the ruby class
262
+ attach_function :g_value_unset, [:pointer], :void
263
+
264
+ attach_function :g_value_set_boolean, [GValue.ptr, :int], :void
265
+ attach_function :g_value_set_int, [GValue.ptr, :int], :void
266
+ attach_function :g_value_set_uint64, [GValue.ptr, :uint64], :void
267
+ attach_function :g_value_set_double, [GValue.ptr, :double], :void
268
+ attach_function :g_value_set_enum, [GValue.ptr, :int], :void
269
+ attach_function :g_value_set_flags, [GValue.ptr, :uint], :void
270
+ attach_function :g_value_set_string, [GValue.ptr, :string], :void
271
+ attach_function :g_value_set_object, [GValue.ptr, :pointer], :void
272
+
273
+ attach_function :g_value_get_boolean, [GValue.ptr], :int
274
+ attach_function :g_value_get_int, [GValue.ptr], :int
275
+ attach_function :g_value_get_uint64, [GValue.ptr], :uint64
276
+ attach_function :g_value_get_double, [GValue.ptr], :double
277
+ attach_function :g_value_get_enum, [GValue.ptr], :int
278
+ attach_function :g_value_get_flags, [GValue.ptr], :int
279
+ attach_function :g_value_get_string, [GValue.ptr], :string
280
+ attach_function :g_value_get_object, [GValue.ptr], :pointer
281
+
282
+ # use :pointer rather than GObject.ptr to avoid casting later
283
+ attach_function :g_object_set_property,
284
+ [:pointer, :string, GValue.ptr], :void
285
+ attach_function :g_object_get_property,
286
+ [:pointer, :string, GValue.ptr], :void
281
287
  end