ffi 0.6.3-x86-mingw32 → 1.0.1-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/History.txt +7 -0
- data/LICENSE +10 -21
- data/README.rdoc +1 -0
- data/Rakefile +4 -2
- data/ext/ffi_c/AbstractMemory.c +103 -38
- data/ext/ffi_c/AbstractMemory.h +15 -22
- data/ext/ffi_c/Buffer.c +61 -22
- data/ext/ffi_c/Call.c +52 -540
- data/ext/ffi_c/Call.h +1 -1
- data/ext/ffi_c/DataConverter.c +62 -0
- data/ext/ffi_c/DynamicLibrary.c +21 -1
- data/ext/ffi_c/Function.c +315 -30
- data/ext/ffi_c/MappedType.c +146 -0
- data/ext/ffi_c/MappedType.h +57 -0
- data/ext/ffi_c/MemoryPointer.c +12 -33
- data/ext/ffi_c/Platform.c +2 -0
- data/ext/ffi_c/Pointer.c +66 -28
- data/ext/ffi_c/Struct.c +19 -306
- data/ext/ffi_c/Struct.h +6 -0
- data/ext/ffi_c/StructByReference.c +150 -0
- data/ext/ffi_c/StructByReference.h +50 -0
- data/ext/ffi_c/StructLayout.c +25 -14
- data/ext/ffi_c/Type.c +39 -68
- data/ext/ffi_c/Type.h +12 -22
- data/ext/ffi_c/Types.c +20 -5
- data/ext/ffi_c/Types.h +7 -7
- data/ext/ffi_c/Variadic.c +21 -17
- data/ext/ffi_c/extconf.rb +4 -0
- data/ext/ffi_c/ffi.c +8 -2
- data/ext/ffi_c/rbffi.h +1 -0
- data/lib/ffi/autopointer.rb +23 -22
- data/lib/ffi/enum.rb +36 -21
- data/lib/ffi/errno.rb +20 -0
- data/lib/ffi/ffi.rb +13 -80
- data/lib/ffi/io.rb +12 -20
- data/lib/ffi/library.rb +109 -92
- data/lib/ffi/managedstruct.rb +1 -1
- data/lib/ffi/memorypointer.rb +15 -21
- data/lib/ffi/platform.rb +24 -28
- data/lib/ffi/pointer.rb +14 -21
- data/lib/ffi/struct.rb +98 -49
- data/lib/ffi/struct_layout_builder.rb +158 -0
- data/lib/ffi/types.rb +99 -128
- data/lib/ffi/union.rb +20 -0
- data/lib/ffi/variadic.rb +33 -22
- data/lib/ffi_c.so +0 -0
- data/spec/ffi/async_callback_spec.rb +23 -0
- data/spec/ffi/callback_spec.rb +62 -0
- data/spec/ffi/custom_param_type.rb +31 -0
- data/spec/ffi/custom_type_spec.rb +73 -0
- data/spec/ffi/enum_spec.rb +19 -0
- data/spec/ffi/ffi_spec.rb +24 -0
- data/spec/ffi/pointer_spec.rb +15 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
- data/spec/ffi/strptr_spec.rb +36 -0
- data/spec/ffi/struct_packed_spec.rb +46 -0
- data/spec/ffi/struct_spec.rb +19 -5
- data/spec/ffi/typedef_spec.rb +14 -0
- data/tasks/setup.rb +2 -1
- metadata +15 -6
- data/ext/ffi_c/AutoPointer.c +0 -60
- data/ext/ffi_c/AutoPointer.h +0 -18
- data/lib/1.8/ffi_c.so +0 -0
- data/lib/1.9/ffi_c.so +0 -0
data/lib/ffi/platform.rb
CHANGED
@@ -2,32 +2,26 @@
|
|
2
2
|
# Copyright (C) 2008, 2009 Wayne Meissner
|
3
3
|
# All rights reserved.
|
4
4
|
#
|
5
|
-
#
|
6
|
-
# modification, are permitted provided that the following conditions are met:
|
5
|
+
# This file is part of ruby-ffi.
|
7
6
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
7
|
+
# All rights reserved.
|
8
|
+
#
|
9
|
+
# This code is free software: you can redistribute it and/or modify it under
|
10
|
+
# the terms of the GNU Lesser General Public License version 3 only, as
|
11
|
+
# published by the Free Software Foundation.
|
12
|
+
#
|
13
|
+
# This code is distributed in the hope that it will be useful, but WITHOUT
|
14
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
16
|
+
# version 3 for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU Lesser General Public License
|
19
|
+
# version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
|
16
20
|
#
|
17
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
-
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
-
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
-
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
-
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
-
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
-
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
-
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
21
|
|
28
22
|
require 'rbconfig'
|
29
23
|
module FFI
|
30
|
-
class PlatformError <
|
24
|
+
class PlatformError < LoadError; end
|
31
25
|
|
32
26
|
module Platform
|
33
27
|
OS = case Config::CONFIG['host_os'].downcase
|
@@ -73,13 +67,7 @@ module FFI
|
|
73
67
|
CONF_DIR = File.dirname(__FILE__)
|
74
68
|
public
|
75
69
|
|
76
|
-
|
77
|
-
"msvcrt"
|
78
|
-
elsif IS_LINUX
|
79
|
-
"libc.so.6"
|
80
|
-
else
|
81
|
-
"c"
|
82
|
-
end
|
70
|
+
|
83
71
|
|
84
72
|
LIBPREFIX = IS_WINDOWS ? '' : 'lib'
|
85
73
|
|
@@ -95,6 +83,14 @@ module FFI
|
|
95
83
|
'so'
|
96
84
|
end
|
97
85
|
|
86
|
+
LIBC = if IS_WINDOWS
|
87
|
+
"msvcrt.dll"
|
88
|
+
elsif IS_LINUX
|
89
|
+
"libc.so.6"
|
90
|
+
else
|
91
|
+
"#{LIBPREFIX}c.#{LIBSUFFIX}"
|
92
|
+
end
|
93
|
+
|
98
94
|
def self.bsd?
|
99
95
|
IS_BSD
|
100
96
|
end
|
data/lib/ffi/pointer.rb
CHANGED
@@ -3,28 +3,20 @@
|
|
3
3
|
# Copyright (c) 2007, 2008 Evan Phoenix
|
4
4
|
# All rights reserved.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
# modification, are permitted provided that the following conditions are met:
|
6
|
+
# This file is part of ruby-ffi.
|
8
7
|
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
8
|
+
# This code is free software: you can redistribute it and/or modify it under
|
9
|
+
# the terms of the GNU Lesser General Public License version 3 only, as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
# This code is distributed in the hope that it will be useful, but WITHOUT
|
13
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
14
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
15
|
+
# version 3 for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
|
17
19
|
#
|
18
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
-
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
22
|
-
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
-
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
-
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
-
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
-
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
-
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
20
|
|
29
21
|
require 'ffi/platform'
|
30
22
|
module FFI
|
@@ -95,10 +87,11 @@ module FFI
|
|
95
87
|
put_bytes(0, str, 0, len)
|
96
88
|
end
|
97
89
|
def write_string(str, len=nil)
|
98
|
-
len = str.
|
90
|
+
len = str.bytesize unless len
|
99
91
|
# Write the string data without NUL termination
|
100
92
|
put_bytes(0, str, 0, len)
|
101
93
|
end
|
94
|
+
|
102
95
|
def read_array_of_type(type, reader, length)
|
103
96
|
ary = []
|
104
97
|
size = FFI.type_size(type)
|
data/lib/ffi/struct.rb
CHANGED
@@ -1,34 +1,28 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (C) 2008
|
2
|
+
# Copyright (C) 2008-2010 Wayne Meissner
|
3
3
|
# Copyright (C) 2008, 2009 Andrea Fazzi
|
4
4
|
# Copyright (C) 2008, 2009 Luc Heinrich
|
5
5
|
#
|
6
6
|
# All rights reserved.
|
7
7
|
#
|
8
|
-
#
|
9
|
-
# modification, are permitted provided that the following conditions are met:
|
8
|
+
# This file is part of ruby-ffi.
|
10
9
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
10
|
+
# This code is free software: you can redistribute it and/or modify it under
|
11
|
+
# the terms of the GNU Lesser General Public License version 3 only, as
|
12
|
+
# published by the Free Software Foundation.
|
13
|
+
#
|
14
|
+
# This code is distributed in the hope that it will be useful, but WITHOUT
|
15
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
17
|
+
# version 3 for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU Lesser General Public License
|
20
|
+
# version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
|
19
21
|
#
|
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
22
|
|
31
23
|
require 'ffi/platform'
|
24
|
+
require 'ffi/struct_layout_builder'
|
25
|
+
|
32
26
|
module FFI
|
33
27
|
|
34
28
|
class StructLayout
|
@@ -53,7 +47,7 @@ module FFI
|
|
53
47
|
|
54
48
|
end
|
55
49
|
|
56
|
-
class
|
50
|
+
class InnerStruct < Field
|
57
51
|
def get(ptr)
|
58
52
|
type.struct_class.new(ptr.slice(self.offset, self.size))
|
59
53
|
end
|
@@ -62,6 +56,21 @@ module FFI
|
|
62
56
|
# raise TypeError, "wrong value type (expected #{type.struct_class}" unless value.is_a(type.struct_class)
|
63
57
|
# end
|
64
58
|
end
|
59
|
+
|
60
|
+
class Mapped < Field
|
61
|
+
def initialize(name, offset, type, orig_field)
|
62
|
+
super(name, offset, type)
|
63
|
+
@orig_field = orig_field
|
64
|
+
end
|
65
|
+
|
66
|
+
def get(ptr)
|
67
|
+
type.from_native(@orig_field.get(ptr), nil)
|
68
|
+
end
|
69
|
+
|
70
|
+
def put(ptr, value)
|
71
|
+
@orig_field.put(ptr, type.to_native(value, nil))
|
72
|
+
end
|
73
|
+
end
|
65
74
|
end
|
66
75
|
|
67
76
|
|
@@ -131,27 +140,60 @@ module FFI
|
|
131
140
|
end
|
132
141
|
|
133
142
|
def self.in
|
134
|
-
:
|
143
|
+
ptr(:in)
|
135
144
|
end
|
136
145
|
|
137
146
|
def self.out
|
138
|
-
:
|
147
|
+
ptr(:out)
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.ptr(flags = :inout)
|
151
|
+
@ref_data_type ||= Type::Mapped.new(StructByReference.new(self))
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.val
|
155
|
+
@val_data_type ||= StructByValue.new(self)
|
139
156
|
end
|
140
157
|
|
141
158
|
def self.by_value
|
142
|
-
|
159
|
+
self.val
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.by_ref(flags = :inout)
|
163
|
+
self.ptr(flags)
|
164
|
+
end
|
165
|
+
|
166
|
+
class ManagedStructConverter < StructByReference
|
167
|
+
|
168
|
+
def initialize(struct_class)
|
169
|
+
super(struct_class)
|
170
|
+
|
171
|
+
raise NoMethodError, "release() not implemented for class #{struct_class}" unless struct_class.respond_to? :release
|
172
|
+
@method = struct_class.method(:release)
|
173
|
+
end
|
174
|
+
|
175
|
+
def from_native(ptr, ctx)
|
176
|
+
struct_class.new(AutoPointer.new(ptr, @method))
|
177
|
+
end
|
143
178
|
end
|
144
179
|
|
180
|
+
def self.auto_ptr
|
181
|
+
@managed_type ||= Type::Mapped.new(ManagedStructConverter.new(self))
|
182
|
+
end
|
145
183
|
|
146
184
|
|
147
185
|
class << self
|
148
186
|
public
|
149
187
|
|
150
188
|
def layout(*spec)
|
189
|
+
# raise RuntimeError, "struct layout already defined for #{self.inspect}" if defined?(@layout)
|
151
190
|
return @layout if spec.size == 0
|
152
191
|
|
153
|
-
builder =
|
192
|
+
builder = StructLayoutBuilder.new
|
154
193
|
builder.union = self < Union
|
194
|
+
builder.packed = @packed if defined?(@packed)
|
195
|
+
builder.alignment = @min_alignment if defined?(@min_alignment)
|
196
|
+
|
155
197
|
if spec[0].kind_of?(Hash)
|
156
198
|
hash_layout(builder, spec)
|
157
199
|
else
|
@@ -159,7 +201,7 @@ module FFI
|
|
159
201
|
end
|
160
202
|
builder.size = @size if defined?(@size) && @size > builder.size
|
161
203
|
cspec = builder.build
|
162
|
-
@layout = cspec unless self ==
|
204
|
+
@layout = cspec unless self == Struct
|
163
205
|
@size = cspec.size
|
164
206
|
return cspec
|
165
207
|
end
|
@@ -172,6 +214,15 @@ module FFI
|
|
172
214
|
FFI::CallbackInfo.new(find_type(ret, mod), params.map { |e| find_type(e, mod) })
|
173
215
|
end
|
174
216
|
|
217
|
+
def packed(packed = 1)
|
218
|
+
@packed = packed
|
219
|
+
end
|
220
|
+
alias :pack :packed
|
221
|
+
|
222
|
+
def aligned(alignment = 1)
|
223
|
+
@min_alignment = alignment
|
224
|
+
end
|
225
|
+
alias :align :aligned
|
175
226
|
|
176
227
|
def enclosing_module
|
177
228
|
begin
|
@@ -182,35 +233,38 @@ module FFI
|
|
182
233
|
end
|
183
234
|
end
|
184
235
|
|
185
|
-
|
186
|
-
|
236
|
+
|
237
|
+
def find_field_type(type, mod = enclosing_module)
|
238
|
+
if type.kind_of?(Class) && type < Struct
|
187
239
|
FFI::Type::Struct.new(type)
|
188
|
-
|
240
|
+
|
241
|
+
elsif type.kind_of?(Class) && type < FFI::StructLayout::Field
|
189
242
|
type
|
190
|
-
|
243
|
+
|
244
|
+
elsif type.kind_of?(::Array)
|
245
|
+
FFI::Type::Array.new(find_field_type(type[0]), type[1])
|
246
|
+
|
247
|
+
else
|
248
|
+
find_type(type, mod)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def find_type(type, mod = enclosing_module)
|
253
|
+
if mod
|
191
254
|
mod.find_type(type)
|
192
255
|
end || FFI.find_type(type)
|
193
256
|
end
|
194
257
|
|
195
|
-
|
196
258
|
private
|
197
259
|
|
198
260
|
def hash_layout(builder, spec)
|
199
261
|
raise "Ruby version not supported" if RUBY_VERSION =~ /1.8.*/
|
200
|
-
|
201
|
-
|
202
|
-
if type.kind_of?(Class) && type < Struct
|
203
|
-
builder.add_struct(name, type)
|
204
|
-
elsif type.kind_of?(::Array)
|
205
|
-
builder.add_array(name, find_type(type[0], mod), type[1])
|
206
|
-
else
|
207
|
-
builder.add_field(name, find_type(type, mod))
|
208
|
-
end
|
262
|
+
spec[0].each do |name, type|
|
263
|
+
builder.add name, find_field_type(type), nil
|
209
264
|
end
|
210
265
|
end
|
211
266
|
|
212
267
|
def array_layout(builder, spec)
|
213
|
-
mod = enclosing_module
|
214
268
|
i = 0
|
215
269
|
while i < spec.size
|
216
270
|
name, type = spec[i, 2]
|
@@ -223,13 +277,8 @@ module FFI
|
|
223
277
|
else
|
224
278
|
offset = nil
|
225
279
|
end
|
226
|
-
|
227
|
-
|
228
|
-
elsif type.kind_of?(::Array)
|
229
|
-
builder.add_array(name, find_type(type[0], mod), type[1], offset)
|
230
|
-
else
|
231
|
-
builder.add_field(name, find_type(type, mod), offset)
|
232
|
-
end
|
280
|
+
|
281
|
+
builder.add name, find_field_type(type), offset
|
233
282
|
end
|
234
283
|
end
|
235
284
|
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2008-2010 Wayne Meissner
|
3
|
+
#
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This file is part of ruby-ffi.
|
7
|
+
#
|
8
|
+
# This code is free software: you can redistribute it and/or modify it under
|
9
|
+
# the terms of the GNU Lesser General Public License version 3 only, as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
# This code is distributed in the hope that it will be useful, but WITHOUT
|
13
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
14
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
15
|
+
# version 3 for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
module FFI
|
22
|
+
class StructLayoutBuilder
|
23
|
+
attr_reader :size, :alignment
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@size = 0
|
27
|
+
@alignment = 1
|
28
|
+
@min_alignment = 1
|
29
|
+
@packed = false
|
30
|
+
@union = false
|
31
|
+
@fields = Array.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def size=(size)
|
35
|
+
@size = size if size > @size
|
36
|
+
end
|
37
|
+
|
38
|
+
def alignment=(align)
|
39
|
+
@alignment = align if align > @alignment
|
40
|
+
@min_alignment = align
|
41
|
+
end
|
42
|
+
|
43
|
+
def union=(is_union)
|
44
|
+
@union = is_union
|
45
|
+
end
|
46
|
+
|
47
|
+
def union?
|
48
|
+
@union
|
49
|
+
end
|
50
|
+
|
51
|
+
def packed=(packed)
|
52
|
+
if packed.is_a?(Fixnum)
|
53
|
+
@alignment = packed
|
54
|
+
@packed = packed
|
55
|
+
else
|
56
|
+
@packed = packed ? 1 : 0
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
NUMBER_TYPES = [
|
62
|
+
Type::INT8,
|
63
|
+
Type::UINT8,
|
64
|
+
Type::INT16,
|
65
|
+
Type::UINT16,
|
66
|
+
Type::INT32,
|
67
|
+
Type::UINT32,
|
68
|
+
Type::LONG,
|
69
|
+
Type::ULONG,
|
70
|
+
Type::INT64,
|
71
|
+
Type::UINT64,
|
72
|
+
Type::FLOAT32,
|
73
|
+
Type::FLOAT64,
|
74
|
+
]
|
75
|
+
|
76
|
+
def add(name, type, offset = nil)
|
77
|
+
|
78
|
+
if offset.nil? || offset == -1
|
79
|
+
offset = @union ? 0 : align(@size, @packed ? [ @packed, type.alignment ].min : [ @min_alignment, type.alignment ].max)
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# If a FFI::Type type was passed in as the field arg, try and convert to a StructLayout::Field instance
|
84
|
+
#
|
85
|
+
field = type.is_a?(StructLayout::Field) ? type : field_for_type(name, offset, type)
|
86
|
+
@fields << field
|
87
|
+
@alignment = [ @alignment, field.alignment ].max unless @packed
|
88
|
+
@size = [ @size, field.size + (@union ? 0 : field.offset) ].max
|
89
|
+
|
90
|
+
return self
|
91
|
+
end
|
92
|
+
|
93
|
+
def add_field(name, type, offset = nil)
|
94
|
+
add(name, type, offset)
|
95
|
+
end
|
96
|
+
|
97
|
+
def add_struct(name, type, offset = nil)
|
98
|
+
add(name, Type::Struct.new(type), offset)
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_array(name, type, count, offset = nil)
|
102
|
+
add(name, Type::Array.new(type, count), offset)
|
103
|
+
end
|
104
|
+
|
105
|
+
def build
|
106
|
+
# Add tail padding if the struct is not packed
|
107
|
+
size = @packed ? @size : align(@size, @alignment)
|
108
|
+
|
109
|
+
StructLayout.new(@fields, size, @alignment)
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def align(offset, align)
|
115
|
+
align + ((offset - 1) & ~(align - 1));
|
116
|
+
end
|
117
|
+
|
118
|
+
def field_for_type(name, offset, type)
|
119
|
+
field_class = case
|
120
|
+
when type.is_a?(Type::Function)
|
121
|
+
StructLayout::Function
|
122
|
+
|
123
|
+
when type.is_a?(Type::Struct)
|
124
|
+
StructLayout::InnerStruct
|
125
|
+
|
126
|
+
when type.is_a?(Type::Array)
|
127
|
+
StructLayout::Array
|
128
|
+
|
129
|
+
when type.is_a?(FFI::Enum)
|
130
|
+
StructLayout::Enum
|
131
|
+
|
132
|
+
when NUMBER_TYPES.include?(type)
|
133
|
+
StructLayout::Number
|
134
|
+
|
135
|
+
when type == Type::POINTER
|
136
|
+
StructLayout::Pointer
|
137
|
+
|
138
|
+
when type == Type::STRING
|
139
|
+
StructLayout::String
|
140
|
+
|
141
|
+
when type.is_a?(Class) && type < StructLayout::Field
|
142
|
+
type
|
143
|
+
|
144
|
+
when type.is_a?(DataConverter)
|
145
|
+
return StructLayout::Mapped.new(name, offset, Type::Mapped.new(type), field_for_type(name, offset, type.native_type))
|
146
|
+
|
147
|
+
when type.is_a?(Type::Mapped)
|
148
|
+
return StructLayout::Mapped.new(name, offset, type, field_for_type(name, offset, type.native_type))
|
149
|
+
|
150
|
+
else
|
151
|
+
raise TypeError, "invalid struct field type #{type.inspect}"
|
152
|
+
end
|
153
|
+
|
154
|
+
field_class.new(name, offset, type)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|