ffi 1.15.5-x64-mingw-ucrt

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 (100) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +338 -0
  3. data/COPYING +49 -0
  4. data/Gemfile +14 -0
  5. data/LICENSE +24 -0
  6. data/LICENSE.SPECS +22 -0
  7. data/README.md +136 -0
  8. data/Rakefile +191 -0
  9. data/ffi.gemspec +42 -0
  10. data/lib/3.1/ffi_c.so +0 -0
  11. data/lib/ffi/abstract_memory.rb +44 -0
  12. data/lib/ffi/autopointer.rb +203 -0
  13. data/lib/ffi/buffer.rb +4 -0
  14. data/lib/ffi/callback.rb +4 -0
  15. data/lib/ffi/data_converter.rb +67 -0
  16. data/lib/ffi/enum.rb +296 -0
  17. data/lib/ffi/errno.rb +43 -0
  18. data/lib/ffi/ffi.rb +47 -0
  19. data/lib/ffi/io.rb +62 -0
  20. data/lib/ffi/library.rb +592 -0
  21. data/lib/ffi/managedstruct.rb +84 -0
  22. data/lib/ffi/memorypointer.rb +1 -0
  23. data/lib/ffi/platform/aarch64-darwin/types.conf +130 -0
  24. data/lib/ffi/platform/aarch64-freebsd/types.conf +128 -0
  25. data/lib/ffi/platform/aarch64-freebsd12/types.conf +181 -0
  26. data/lib/ffi/platform/aarch64-linux/types.conf +104 -0
  27. data/lib/ffi/platform/aarch64-openbsd/types.conf +134 -0
  28. data/lib/ffi/platform/arm-freebsd/types.conf +152 -0
  29. data/lib/ffi/platform/arm-freebsd12/types.conf +152 -0
  30. data/lib/ffi/platform/arm-linux/types.conf +132 -0
  31. data/lib/ffi/platform/i386-cygwin/types.conf +3 -0
  32. data/lib/ffi/platform/i386-darwin/types.conf +100 -0
  33. data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  34. data/lib/ffi/platform/i386-freebsd12/types.conf +152 -0
  35. data/lib/ffi/platform/i386-gnu/types.conf +107 -0
  36. data/lib/ffi/platform/i386-linux/types.conf +103 -0
  37. data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  38. data/lib/ffi/platform/i386-openbsd/types.conf +128 -0
  39. data/lib/ffi/platform/i386-solaris/types.conf +122 -0
  40. data/lib/ffi/platform/i386-windows/types.conf +52 -0
  41. data/lib/ffi/platform/ia64-linux/types.conf +104 -0
  42. data/lib/ffi/platform/mips-linux/types.conf +102 -0
  43. data/lib/ffi/platform/mips64-linux/types.conf +104 -0
  44. data/lib/ffi/platform/mips64el-linux/types.conf +104 -0
  45. data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  46. data/lib/ffi/platform/mipsisa32r6-linux/types.conf +102 -0
  47. data/lib/ffi/platform/mipsisa32r6el-linux/types.conf +102 -0
  48. data/lib/ffi/platform/mipsisa64r6-linux/types.conf +104 -0
  49. data/lib/ffi/platform/mipsisa64r6el-linux/types.conf +104 -0
  50. data/lib/ffi/platform/powerpc-aix/types.conf +180 -0
  51. data/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
  52. data/lib/ffi/platform/powerpc-linux/types.conf +130 -0
  53. data/lib/ffi/platform/powerpc-openbsd/types.conf +156 -0
  54. data/lib/ffi/platform/powerpc64-linux/types.conf +104 -0
  55. data/lib/ffi/platform/powerpc64le-linux/types.conf +100 -0
  56. data/lib/ffi/platform/riscv64-linux/types.conf +104 -0
  57. data/lib/ffi/platform/s390-linux/types.conf +102 -0
  58. data/lib/ffi/platform/s390x-linux/types.conf +102 -0
  59. data/lib/ffi/platform/sparc-linux/types.conf +102 -0
  60. data/lib/ffi/platform/sparc-solaris/types.conf +128 -0
  61. data/lib/ffi/platform/sparc64-linux/types.conf +102 -0
  62. data/lib/ffi/platform/sparcv9-openbsd/types.conf +156 -0
  63. data/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
  64. data/lib/ffi/platform/x86_64-cygwin/types.conf +3 -0
  65. data/lib/ffi/platform/x86_64-darwin/types.conf +130 -0
  66. data/lib/ffi/platform/x86_64-dragonflybsd/types.conf +130 -0
  67. data/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
  68. data/lib/ffi/platform/x86_64-freebsd12/types.conf +158 -0
  69. data/lib/ffi/platform/x86_64-haiku/types.conf +117 -0
  70. data/lib/ffi/platform/x86_64-linux/types.conf +132 -0
  71. data/lib/ffi/platform/x86_64-msys/types.conf +119 -0
  72. data/lib/ffi/platform/x86_64-netbsd/types.conf +128 -0
  73. data/lib/ffi/platform/x86_64-openbsd/types.conf +134 -0
  74. data/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
  75. data/lib/ffi/platform/x86_64-windows/types.conf +52 -0
  76. data/lib/ffi/platform.rb +185 -0
  77. data/lib/ffi/pointer.rb +167 -0
  78. data/lib/ffi/struct.rb +316 -0
  79. data/lib/ffi/struct_by_reference.rb +72 -0
  80. data/lib/ffi/struct_layout.rb +96 -0
  81. data/lib/ffi/struct_layout_builder.rb +227 -0
  82. data/lib/ffi/tools/const_generator.rb +232 -0
  83. data/lib/ffi/tools/generator.rb +105 -0
  84. data/lib/ffi/tools/generator_task.rb +32 -0
  85. data/lib/ffi/tools/struct_generator.rb +195 -0
  86. data/lib/ffi/tools/types_generator.rb +137 -0
  87. data/lib/ffi/types.rb +194 -0
  88. data/lib/ffi/union.rb +43 -0
  89. data/lib/ffi/variadic.rb +69 -0
  90. data/lib/ffi/version.rb +3 -0
  91. data/lib/ffi.rb +27 -0
  92. data/rakelib/ffi_gem_helper.rb +65 -0
  93. data/samples/getlogin.rb +8 -0
  94. data/samples/getpid.rb +8 -0
  95. data/samples/gettimeofday.rb +18 -0
  96. data/samples/hello.rb +8 -0
  97. data/samples/inotify.rb +60 -0
  98. data/samples/pty.rb +75 -0
  99. data/samples/qsort.rb +20 -0
  100. metadata +207 -0
data/lib/ffi/struct.rb ADDED
@@ -0,0 +1,316 @@
1
+ #
2
+ # Copyright (C) 2008-2010 Wayne Meissner
3
+ # Copyright (C) 2008, 2009 Andrea Fazzi
4
+ # Copyright (C) 2008, 2009 Luc Heinrich
5
+ #
6
+ # This file is part of ruby-ffi.
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice, this
14
+ # list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the Ruby FFI project nor the names of its contributors
19
+ # may be used to endorse or promote products derived from this software
20
+ # without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
26
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ #
33
+
34
+ require 'ffi/platform'
35
+ require 'ffi/struct_layout'
36
+ require 'ffi/struct_layout_builder'
37
+ require 'ffi/struct_by_reference'
38
+
39
+ module FFI
40
+
41
+ class Struct
42
+
43
+ # Get struct size
44
+ # @return [Numeric]
45
+ def size
46
+ self.class.size
47
+ end
48
+
49
+ # @return [Fixnum] Struct alignment
50
+ def alignment
51
+ self.class.alignment
52
+ end
53
+ alias_method :align, :alignment
54
+
55
+ # (see FFI::StructLayout#offset_of)
56
+ def offset_of(name)
57
+ self.class.offset_of(name)
58
+ end
59
+
60
+ # (see FFI::StructLayout#members)
61
+ def members
62
+ self.class.members
63
+ end
64
+
65
+ # @return [Array]
66
+ # Get array of values from Struct fields.
67
+ def values
68
+ members.map { |m| self[m] }
69
+ end
70
+
71
+ # (see FFI::StructLayout#offsets)
72
+ def offsets
73
+ self.class.offsets
74
+ end
75
+
76
+ # Clear the struct content.
77
+ # @return [self]
78
+ def clear
79
+ pointer.clear
80
+ self
81
+ end
82
+
83
+ # Get {Pointer} to struct content.
84
+ # @return [AbstractMemory]
85
+ def to_ptr
86
+ pointer
87
+ end
88
+
89
+ # Get struct size
90
+ # @return [Numeric]
91
+ def self.size
92
+ defined?(@layout) ? @layout.size : defined?(@size) ? @size : 0
93
+ end
94
+
95
+ # set struct size
96
+ # @param [Numeric] size
97
+ # @return [size]
98
+ def self.size=(size)
99
+ raise ArgumentError, "Size already set" if defined?(@size) || defined?(@layout)
100
+ @size = size
101
+ end
102
+
103
+ # @return (see Struct#alignment)
104
+ def self.alignment
105
+ @layout.alignment
106
+ end
107
+
108
+ # (see FFI::Type#members)
109
+ def self.members
110
+ @layout.members
111
+ end
112
+
113
+ # (see FFI::StructLayout#offsets)
114
+ def self.offsets
115
+ @layout.offsets
116
+ end
117
+
118
+ # (see FFI::StructLayout#offset_of)
119
+ def self.offset_of(name)
120
+ @layout.offset_of(name)
121
+ end
122
+
123
+ def self.in
124
+ ptr(:in)
125
+ end
126
+
127
+ def self.out
128
+ ptr(:out)
129
+ end
130
+
131
+ def self.ptr(flags = :inout)
132
+ @ref_data_type ||= Type::Mapped.new(StructByReference.new(self))
133
+ end
134
+
135
+ def self.val
136
+ @val_data_type ||= StructByValue.new(self)
137
+ end
138
+
139
+ def self.by_value
140
+ self.val
141
+ end
142
+
143
+ def self.by_ref(flags = :inout)
144
+ self.ptr(flags)
145
+ end
146
+
147
+ class ManagedStructConverter < StructByReference
148
+
149
+ # @param [Struct] struct_class
150
+ def initialize(struct_class)
151
+ super(struct_class)
152
+
153
+ raise NoMethodError, "release() not implemented for class #{struct_class}" unless struct_class.respond_to? :release
154
+ @method = struct_class.method(:release)
155
+ end
156
+
157
+ # @param [Pointer] ptr
158
+ # @param [nil] ctx
159
+ # @return [Struct]
160
+ def from_native(ptr, ctx)
161
+ struct_class.new(AutoPointer.new(ptr, @method))
162
+ end
163
+ end
164
+
165
+ def self.auto_ptr
166
+ @managed_type ||= Type::Mapped.new(ManagedStructConverter.new(self))
167
+ end
168
+
169
+
170
+ class << self
171
+ public
172
+
173
+ # @return [StructLayout]
174
+ # @overload layout
175
+ # @return [StructLayout]
176
+ # Get struct layout.
177
+ # @overload layout(*spec)
178
+ # @param [Array<Symbol, Integer>,Array(Hash)] spec
179
+ # @return [StructLayout]
180
+ # Create struct layout from +spec+.
181
+ # @example Creating a layout from an array +spec+
182
+ # class MyStruct < Struct
183
+ # layout :field1, :int,
184
+ # :field2, :pointer,
185
+ # :field3, :string
186
+ # end
187
+ # @example Creating a layout from an array +spec+ with offset
188
+ # class MyStructWithOffset < Struct
189
+ # layout :field1, :int,
190
+ # :field2, :pointer, 6, # set offset to 6 for this field
191
+ # :field3, :string
192
+ # end
193
+ # @example Creating a layout from a hash +spec+
194
+ # class MyStructFromHash < Struct
195
+ # layout :field1 => :int,
196
+ # :field2 => :pointer,
197
+ # :field3 => :string
198
+ # end
199
+ # @example Creating a layout with pointers to functions
200
+ # class MyFunctionTable < Struct
201
+ # layout :function1, callback([:int, :int], :int),
202
+ # :function2, callback([:pointer], :void),
203
+ # :field3, :string
204
+ # end
205
+ def layout(*spec)
206
+ warn "[DEPRECATION] Struct layout is already defined for class #{self.inspect}. Redefinition as in #{caller[0]} will be disallowed in ffi-2.0." if defined?(@layout)
207
+ return @layout if spec.size == 0
208
+
209
+ builder = StructLayoutBuilder.new
210
+ builder.union = self < Union
211
+ builder.packed = @packed if defined?(@packed)
212
+ builder.alignment = @min_alignment if defined?(@min_alignment)
213
+
214
+ if spec[0].kind_of?(Hash)
215
+ hash_layout(builder, spec)
216
+ else
217
+ array_layout(builder, spec)
218
+ end
219
+ builder.size = @size if defined?(@size) && @size > builder.size
220
+ cspec = builder.build
221
+ @layout = cspec unless self == Struct
222
+ @size = cspec.size
223
+ return cspec
224
+ end
225
+
226
+
227
+ protected
228
+
229
+ def callback(params, ret)
230
+ mod = enclosing_module
231
+ ret_type = find_type(ret, mod)
232
+ if ret_type == Type::STRING
233
+ raise TypeError, ":string is not allowed as return type of callbacks"
234
+ end
235
+ FFI::CallbackInfo.new(ret_type, params.map { |e| find_type(e, mod) })
236
+ end
237
+
238
+ def packed(packed = 1)
239
+ @packed = packed
240
+ end
241
+ alias :pack :packed
242
+
243
+ def aligned(alignment = 1)
244
+ @min_alignment = alignment
245
+ end
246
+ alias :align :aligned
247
+
248
+ def enclosing_module
249
+ begin
250
+ mod = self.name.split("::")[0..-2].inject(Object) { |obj, c| obj.const_get(c) }
251
+ if mod.respond_to?(:find_type) && (mod.is_a?(FFI::Library) || mod < FFI::Struct)
252
+ mod
253
+ end
254
+ rescue Exception
255
+ nil
256
+ end
257
+ end
258
+
259
+
260
+ def find_field_type(type, mod = enclosing_module)
261
+ if type.kind_of?(Class) && type < Struct
262
+ FFI::Type::Struct.new(type)
263
+
264
+ elsif type.kind_of?(Class) && type < FFI::StructLayout::Field
265
+ type
266
+
267
+ elsif type.kind_of?(::Array)
268
+ FFI::Type::Array.new(find_field_type(type[0]), type[1])
269
+
270
+ else
271
+ find_type(type, mod)
272
+ end
273
+ end
274
+
275
+ def find_type(type, mod = enclosing_module)
276
+ if mod
277
+ mod.find_type(type)
278
+ end || FFI.find_type(type)
279
+ end
280
+
281
+ private
282
+
283
+ # @param [StructLayoutBuilder] builder
284
+ # @param [Hash] spec
285
+ # @return [builder]
286
+ # Add hash +spec+ to +builder+.
287
+ def hash_layout(builder, spec)
288
+ spec[0].each do |name, type|
289
+ builder.add name, find_field_type(type), nil
290
+ end
291
+ end
292
+
293
+ # @param [StructLayoutBuilder] builder
294
+ # @param [Array<Symbol, Integer>] spec
295
+ # @return [builder]
296
+ # Add array +spec+ to +builder+.
297
+ def array_layout(builder, spec)
298
+ i = 0
299
+ while i < spec.size
300
+ name, type = spec[i, 2]
301
+ i += 2
302
+
303
+ # If the next param is a Integer, it specifies the offset
304
+ if spec[i].kind_of?(Integer)
305
+ offset = spec[i]
306
+ i += 1
307
+ else
308
+ offset = nil
309
+ end
310
+
311
+ builder.add name, find_field_type(type), offset
312
+ end
313
+ end
314
+ end
315
+ end
316
+ end
@@ -0,0 +1,72 @@
1
+ #
2
+ # Copyright (C) 2010 Wayne Meissner
3
+ #
4
+ # This file is part of ruby-ffi.
5
+ #
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice, this
12
+ # list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above copyright notice
14
+ # this list of conditions and the following disclaimer in the documentation
15
+ # and/or other materials provided with the distribution.
16
+ # * Neither the name of the Ruby FFI project nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this software
18
+ # without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#
30
+
31
+ module FFI
32
+ # This class includes the {FFI::DataConverter} module.
33
+ class StructByReference
34
+ include DataConverter
35
+
36
+ attr_reader :struct_class
37
+
38
+ # @param [Struct] struct_class
39
+ def initialize(struct_class)
40
+ unless Class === struct_class and struct_class < FFI::Struct
41
+ raise TypeError, 'wrong type (expected subclass of FFI::Struct)'
42
+ end
43
+ @struct_class = struct_class
44
+ end
45
+
46
+ # Always get {FFI::Type}::POINTER.
47
+ def native_type
48
+ FFI::Type::POINTER
49
+ end
50
+
51
+ # @param [nil, Struct] value
52
+ # @param [nil] ctx
53
+ # @return [AbstractMemory] Pointer on +value+.
54
+ def to_native(value, ctx)
55
+ return Pointer::NULL if value.nil?
56
+
57
+ unless @struct_class === value
58
+ raise TypeError, "wrong argument type #{value.class} (expected #{@struct_class})"
59
+ end
60
+
61
+ value.pointer
62
+ end
63
+
64
+ # @param [AbstractMemory] value
65
+ # @param [nil] ctx
66
+ # @return [Struct]
67
+ # Create a struct from content of memory +value+.
68
+ def from_native(value, ctx)
69
+ @struct_class.new(value)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,96 @@
1
+ #
2
+ # Copyright (C) 2008-2010 Wayne Meissner
3
+ # Copyright (C) 2008, 2009 Andrea Fazzi
4
+ # Copyright (C) 2008, 2009 Luc Heinrich
5
+ #
6
+ # This file is part of ruby-ffi.
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice, this
14
+ # list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the Ruby FFI project nor the names of its contributors
19
+ # may be used to endorse or promote products derived from this software
20
+ # without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
26
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ #
33
+
34
+ module FFI
35
+
36
+ class StructLayout
37
+
38
+ # @return [Array<Array(Symbol, Numeric)>
39
+ # Get an array of tuples (field name, offset of the field).
40
+ def offsets
41
+ members.map { |m| [ m, self[m].offset ] }
42
+ end
43
+
44
+ # @return [Numeric]
45
+ # Get the offset of a field.
46
+ def offset_of(field_name)
47
+ self[field_name].offset
48
+ end
49
+
50
+ # An enum {Field} in a {StructLayout}.
51
+ class Enum < Field
52
+
53
+ # @param [AbstractMemory] ptr pointer on a {Struct}
54
+ # @return [Object]
55
+ # Get an object of type {#type} from memory pointed by +ptr+.
56
+ def get(ptr)
57
+ type.find(ptr.get_int(offset))
58
+ end
59
+
60
+ # @param [AbstractMemory] ptr pointer on a {Struct}
61
+ # @param value
62
+ # @return [nil]
63
+ # Set +value+ into memory pointed by +ptr+.
64
+ def put(ptr, value)
65
+ ptr.put_int(offset, type.find(value))
66
+ end
67
+
68
+ end
69
+
70
+ class InnerStruct < Field
71
+ def get(ptr)
72
+ type.struct_class.new(ptr.slice(self.offset, self.size))
73
+ end
74
+
75
+ def put(ptr, value)
76
+ raise TypeError, "wrong value type (expected #{type.struct_class})" unless value.is_a?(type.struct_class)
77
+ ptr.slice(self.offset, self.size).__copy_from__(value.pointer, self.size)
78
+ end
79
+ end
80
+
81
+ class Mapped < Field
82
+ def initialize(name, offset, type, orig_field)
83
+ super(name, offset, type)
84
+ @orig_field = orig_field
85
+ end
86
+
87
+ def get(ptr)
88
+ type.from_native(@orig_field.get(ptr), nil)
89
+ end
90
+
91
+ def put(ptr, value)
92
+ @orig_field.put(ptr, type.to_native(value, nil))
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,227 @@
1
+ #
2
+ # Copyright (C) 2008-2010 Wayne Meissner
3
+ #
4
+ # This file is part of ruby-ffi.
5
+ #
6
+ # All rights reserved.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice, this
12
+ # list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above copyright notice
14
+ # this list of conditions and the following disclaimer in the documentation
15
+ # and/or other materials provided with the distribution.
16
+ # * Neither the name of the Ruby FFI project nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this software
18
+ # without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ #
31
+
32
+ module FFI
33
+
34
+ # Build a {StructLayout struct layout}.
35
+ class StructLayoutBuilder
36
+ attr_reader :size
37
+ attr_reader :alignment
38
+
39
+ def initialize
40
+ @size = 0
41
+ @alignment = 1
42
+ @min_alignment = 1
43
+ @packed = false
44
+ @union = false
45
+ @fields = Array.new
46
+ end
47
+
48
+ # Set size attribute with +size+ only if +size+ is greater than attribute value.
49
+ # @param [Numeric] size
50
+ def size=(size)
51
+ @size = size if size > @size
52
+ end
53
+
54
+ # Set alignment attribute with +align+ only if it is greater than attribute value.
55
+ # @param [Numeric] align
56
+ def alignment=(align)
57
+ @alignment = align if align > @alignment
58
+ @min_alignment = align
59
+ end
60
+
61
+ # Set union attribute.
62
+ # Set to +true+ to build a {Union} instead of a {Struct}.
63
+ # @param [Boolean] is_union
64
+ # @return [is_union]
65
+ def union=(is_union)
66
+ @union = is_union
67
+ end
68
+
69
+ # Building a {Union} or a {Struct} ?
70
+ #
71
+ # @return [Boolean]
72
+ #
73
+ def union?
74
+ @union
75
+ end
76
+
77
+ # Set packed attribute
78
+ # @overload packed=(packed) Set alignment and packed attributes to
79
+ # +packed+.
80
+ #
81
+ # @param [Fixnum] packed
82
+ #
83
+ # @return [packed]
84
+ # @overload packed=(packed) Set packed attribute.
85
+ # @param packed
86
+ #
87
+ # @return [0,1]
88
+ #
89
+ def packed=(packed)
90
+ if packed.is_a?(0.class)
91
+ @alignment = packed
92
+ @packed = packed
93
+ else
94
+ @packed = packed ? 1 : 0
95
+ end
96
+ end
97
+
98
+
99
+ # List of number types
100
+ NUMBER_TYPES = [
101
+ Type::INT8,
102
+ Type::UINT8,
103
+ Type::INT16,
104
+ Type::UINT16,
105
+ Type::INT32,
106
+ Type::UINT32,
107
+ Type::LONG,
108
+ Type::ULONG,
109
+ Type::INT64,
110
+ Type::UINT64,
111
+ Type::FLOAT32,
112
+ Type::FLOAT64,
113
+ Type::LONGDOUBLE,
114
+ Type::BOOL,
115
+ ]
116
+
117
+ # @param [String, Symbol] name name of the field
118
+ # @param [Array, DataConverter, Struct, StructLayout::Field, Symbol, Type] type type of the field
119
+ # @param [Numeric, nil] offset
120
+ # @return [self]
121
+ # Add a field to the builder.
122
+ # @note Setting +offset+ to +nil+ or +-1+ is equivalent to +0+.
123
+ def add(name, type, offset = nil)
124
+
125
+ if offset.nil? || offset == -1
126
+ offset = @union ? 0 : align(@size, @packed ? [ @packed, type.alignment ].min : [ @min_alignment, type.alignment ].max)
127
+ end
128
+
129
+ #
130
+ # If a FFI::Type type was passed in as the field arg, try and convert to a StructLayout::Field instance
131
+ #
132
+ field = type.is_a?(StructLayout::Field) ? type : field_for_type(name, offset, type)
133
+ @fields << field
134
+ @alignment = [ @alignment, field.alignment ].max unless @packed
135
+ @size = [ @size, field.size + (@union ? 0 : field.offset) ].max
136
+
137
+ return self
138
+ end
139
+
140
+ # @param (see #add)
141
+ # @return (see #add)
142
+ # Same as {#add}.
143
+ # @see #add
144
+ def add_field(name, type, offset = nil)
145
+ add(name, type, offset)
146
+ end
147
+
148
+ # @param (see #add)
149
+ # @return (see #add)
150
+ # Add a struct as a field to the builder.
151
+ def add_struct(name, type, offset = nil)
152
+ add(name, Type::Struct.new(type), offset)
153
+ end
154
+
155
+ # @param name (see #add)
156
+ # @param type (see #add)
157
+ # @param [Numeric] count array length
158
+ # @param offset (see #add)
159
+ # @return (see #add)
160
+ # Add an array as a field to the builder.
161
+ def add_array(name, type, count, offset = nil)
162
+ add(name, Type::Array.new(type, count), offset)
163
+ end
164
+
165
+ # @return [StructLayout]
166
+ # Build and return the struct layout.
167
+ def build
168
+ # Add tail padding if the struct is not packed
169
+ size = @packed ? @size : align(@size, @alignment)
170
+
171
+ layout = StructLayout.new(@fields, size, @alignment)
172
+ layout.__union! if @union
173
+ layout
174
+ end
175
+
176
+ private
177
+
178
+ # @param [Numeric] offset
179
+ # @param [Numeric] align
180
+ # @return [Numeric]
181
+ def align(offset, align)
182
+ align + ((offset - 1) & ~(align - 1));
183
+ end
184
+
185
+ # @param (see #add)
186
+ # @return [StructLayout::Field]
187
+ def field_for_type(name, offset, type)
188
+ field_class = case
189
+ when type.is_a?(Type::Function)
190
+ StructLayout::Function
191
+
192
+ when type.is_a?(Type::Struct)
193
+ StructLayout::InnerStruct
194
+
195
+ when type.is_a?(Type::Array)
196
+ StructLayout::Array
197
+
198
+ when type.is_a?(FFI::Enum)
199
+ StructLayout::Enum
200
+
201
+ when NUMBER_TYPES.include?(type)
202
+ StructLayout::Number
203
+
204
+ when type == Type::POINTER
205
+ StructLayout::Pointer
206
+
207
+ when type == Type::STRING
208
+ StructLayout::String
209
+
210
+ when type.is_a?(Class) && type < StructLayout::Field
211
+ type
212
+
213
+ when type.is_a?(DataConverter)
214
+ return StructLayout::Mapped.new(name, offset, Type::Mapped.new(type), field_for_type(name, offset, type.native_type))
215
+
216
+ when type.is_a?(Type::Mapped)
217
+ return StructLayout::Mapped.new(name, offset, type, field_for_type(name, offset, type.native_type))
218
+
219
+ else
220
+ raise TypeError, "invalid struct field type #{type.inspect}"
221
+ end
222
+
223
+ field_class.new(name, offset, type)
224
+ end
225
+ end
226
+
227
+ end