ffi 1.2.1 → 1.3.0
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/README.md +10 -5
- data/ext/ffi_c/ArrayType.c +6 -2
- data/ext/ffi_c/Buffer.c +3 -1
- data/ext/ffi_c/Call.c +12 -21
- data/ext/ffi_c/FunctionInfo.c +27 -2
- data/ext/ffi_c/MappedType.c +1 -2
- data/ext/ffi_c/MemoryPointer.c +35 -4
- data/ext/ffi_c/Pointer.c +5 -4
- data/ext/ffi_c/Struct.c +125 -8
- data/ext/ffi_c/StructByReference.c +33 -0
- data/ext/ffi_c/StructByValue.c +2 -2
- data/ext/ffi_c/StructLayout.c +135 -1
- data/ext/ffi_c/Type.c +1 -0
- data/ext/ffi_c/extconf.rb +1 -1
- data/ffi.gemspec +1 -1
- data/lib/ffi.rb +2 -1
- data/lib/ffi/library.rb +2 -0
- data/lib/ffi/managedstruct.rb +37 -37
- data/lib/ffi/struct.rb +74 -1
- data/lib/ffi/struct_layout_builder.rb +50 -1
- data/lib/ffi/tools/generator.rb +2 -0
- data/lib/ffi/tools/generator_task.rb +1 -0
- data/lib/ffi/tools/types_generator.rb +2 -0
- data/libtest/Benchmark.c +1 -15
- data/libtest/BoolTest.c +2 -16
- data/libtest/BufferTest.c +3 -17
- data/libtest/ClosureTest.c +1 -15
- data/libtest/EnumTest.c +1 -15
- data/libtest/FunctionTest.c +2 -16
- data/libtest/GlobalVariable.c +2 -16
- data/libtest/LastErrorTest.c +2 -16
- data/libtest/NumberTest.c +1 -15
- data/libtest/PointerTest.c +1 -15
- data/libtest/ReferenceTest.c +1 -15
- data/libtest/StringTest.c +1 -15
- data/libtest/StructTest.c +1 -15
- data/libtest/UnionTest.c +1 -15
- data/libtest/VariadicTest.c +2 -16
- data/spec/ffi/async_callback_spec.rb +3 -14
- data/spec/ffi/bool_spec.rb +7 -18
- data/spec/ffi/buffer_spec.rb +26 -37
- data/spec/ffi/callback_spec.rb +96 -107
- data/spec/ffi/custom_param_type.rb +2 -13
- data/spec/ffi/custom_type_spec.rb +1 -12
- data/spec/ffi/dup_spec.rb +7 -18
- data/spec/ffi/enum_spec.rb +128 -139
- data/spec/ffi/errno_spec.rb +2 -13
- data/spec/ffi/ffi_spec.rb +4 -15
- data/spec/ffi/function_spec.rb +6 -17
- data/spec/ffi/library_spec.rb +26 -26
- data/spec/ffi/long_double.rb +1 -12
- data/spec/ffi/managed_struct_spec.rb +3 -18
- data/spec/ffi/number_spec.rb +32 -43
- data/spec/ffi/pointer_spec.rb +7 -22
- data/spec/ffi/rbx/memory_pointer_spec.rb +17 -17
- data/spec/ffi/rbx/struct_spec.rb +2 -2
- data/spec/ffi/spec_helper.rb +10 -12
- data/spec/ffi/string_spec.rb +9 -20
- data/spec/ffi/strptr_spec.rb +2 -13
- data/spec/ffi/struct_callback_spec.rb +3 -14
- data/spec/ffi/struct_initialize_spec.rb +3 -14
- data/spec/ffi/struct_packed_spec.rb +7 -18
- data/spec/ffi/struct_spec.rb +93 -104
- data/spec/ffi/typedef_spec.rb +5 -16
- data/spec/ffi/union_spec.rb +4 -15
- data/spec/ffi/variadic_spec.rb +7 -18
- metadata +73 -58
data/lib/ffi/struct.rb
CHANGED
@@ -27,20 +27,32 @@ module FFI
|
|
27
27
|
|
28
28
|
class StructLayout
|
29
29
|
|
30
|
+
# @return [Array<Array(Symbol, Numeric)>
|
31
|
+
# Get an array of tuples (field name, offset of the field).
|
30
32
|
def offsets
|
31
33
|
members.map { |m| [ m, self[m].offset ] }
|
32
34
|
end
|
33
35
|
|
36
|
+
# @return [Numeric]
|
37
|
+
# Get the offset of a field.
|
34
38
|
def offset_of(field_name)
|
35
39
|
self[field_name].offset
|
36
40
|
end
|
37
41
|
|
42
|
+
# An enum {Field} in a {StructLayout}.
|
38
43
|
class Enum < Field
|
39
|
-
|
44
|
+
|
45
|
+
# @param [AbstractMemory] ptr pointer on a {Struct}
|
46
|
+
# @return [Object]
|
47
|
+
# Get an object of type {#type} from memory pointed by +ptr+.
|
40
48
|
def get(ptr)
|
41
49
|
type.find(ptr.get_int(offset))
|
42
50
|
end
|
43
51
|
|
52
|
+
# @param [AbstractMemory] ptr pointer on a {Struct}
|
53
|
+
# @param value
|
54
|
+
# @return [nil]
|
55
|
+
# Set +value+ into memory pointed by +ptr+.
|
44
56
|
def put(ptr, value)
|
45
57
|
ptr.put_int(offset, type.find(value))
|
46
58
|
end
|
@@ -77,61 +89,82 @@ module FFI
|
|
77
89
|
|
78
90
|
class Struct
|
79
91
|
|
92
|
+
# Get struct size
|
93
|
+
# @return [Numeric]
|
80
94
|
def size
|
81
95
|
self.class.size
|
82
96
|
end
|
83
97
|
|
98
|
+
# @return [Fixnum] Struct alignment
|
84
99
|
def alignment
|
85
100
|
self.class.alignment
|
86
101
|
end
|
87
102
|
alias_method :align, :alignment
|
88
103
|
|
104
|
+
# (see FFI::StructLayout#offset_of)
|
89
105
|
def offset_of(name)
|
90
106
|
self.class.offset_of(name)
|
91
107
|
end
|
92
108
|
|
109
|
+
# (see FFI::StructLayout#members)
|
93
110
|
def members
|
94
111
|
self.class.members
|
95
112
|
end
|
96
113
|
|
114
|
+
# @return [Array]
|
115
|
+
# Get array of values from Struct fields.
|
97
116
|
def values
|
98
117
|
members.map { |m| self[m] }
|
99
118
|
end
|
100
119
|
|
120
|
+
# (see FFI::StructLayout#offsets)
|
101
121
|
def offsets
|
102
122
|
self.class.offsets
|
103
123
|
end
|
104
124
|
|
125
|
+
# Clear the struct content.
|
126
|
+
# @return [self]
|
105
127
|
def clear
|
106
128
|
pointer.clear
|
107
129
|
self
|
108
130
|
end
|
109
131
|
|
132
|
+
# Get {Pointer} to struct content.
|
133
|
+
# @return [AbstractMemory]
|
110
134
|
def to_ptr
|
111
135
|
pointer
|
112
136
|
end
|
113
137
|
|
138
|
+
# Get struct size
|
139
|
+
# @return [Numeric]
|
114
140
|
def self.size
|
115
141
|
defined?(@layout) ? @layout.size : defined?(@size) ? @size : 0
|
116
142
|
end
|
117
143
|
|
144
|
+
# set struct size
|
145
|
+
# @param [Numeric] size
|
146
|
+
# @return [size]
|
118
147
|
def self.size=(size)
|
119
148
|
raise ArgumentError, "Size already set" if defined?(@size) || defined?(@layout)
|
120
149
|
@size = size
|
121
150
|
end
|
122
151
|
|
152
|
+
# @return (see Struct#alignment)
|
123
153
|
def self.alignment
|
124
154
|
@layout.alignment
|
125
155
|
end
|
126
156
|
|
157
|
+
# (see FFI::Type#members)
|
127
158
|
def self.members
|
128
159
|
@layout.members
|
129
160
|
end
|
130
161
|
|
162
|
+
# (see FFI::StructLayout#offsets)
|
131
163
|
def self.offsets
|
132
164
|
@layout.offsets
|
133
165
|
end
|
134
166
|
|
167
|
+
# (see FFI::StructLayout#offset_of)
|
135
168
|
def self.offset_of(name)
|
136
169
|
@layout.offset_of(name)
|
137
170
|
end
|
@@ -162,6 +195,7 @@ module FFI
|
|
162
195
|
|
163
196
|
class ManagedStructConverter < StructByReference
|
164
197
|
|
198
|
+
# @param [Struct] struct_class
|
165
199
|
def initialize(struct_class)
|
166
200
|
super(struct_class)
|
167
201
|
|
@@ -169,6 +203,9 @@ module FFI
|
|
169
203
|
@method = struct_class.method(:release)
|
170
204
|
end
|
171
205
|
|
206
|
+
# @param [Pointer] ptr
|
207
|
+
# @param [nil] ctx
|
208
|
+
# @return [Struct]
|
172
209
|
def from_native(ptr, ctx)
|
173
210
|
struct_class.new(AutoPointer.new(ptr, @method))
|
174
211
|
end
|
@@ -182,6 +219,33 @@ module FFI
|
|
182
219
|
class << self
|
183
220
|
public
|
184
221
|
|
222
|
+
# @return [StructLayout]
|
223
|
+
# @overload layout
|
224
|
+
# @return [StructLayout]
|
225
|
+
# Get struct layout.
|
226
|
+
# @overload layout(*spec)
|
227
|
+
# @param [Array<Symbol, Integer>,Array(Hash)] spec
|
228
|
+
# @return [StructLayout]
|
229
|
+
# Create struct layout from +spec+.
|
230
|
+
# @example Creating a layout from an array +spec+
|
231
|
+
# class MyStruct < Struct
|
232
|
+
# layout :field1, :int,
|
233
|
+
# :field2, :pointer,
|
234
|
+
# :field3, :string
|
235
|
+
# end
|
236
|
+
# @example Creating a layout from an array +spec+ with offset
|
237
|
+
# class MyStructWithOffset < Struct
|
238
|
+
# layout :field1, :int,
|
239
|
+
# :field2, :pointer, 6, # set offset to 6 for this field
|
240
|
+
# :field3, :string
|
241
|
+
# end
|
242
|
+
# @example Creating a layout from a hash +spec+ (Ruby 1.9 only)
|
243
|
+
# class MyStructFromHash < Struct
|
244
|
+
# layout :field1 => :int,
|
245
|
+
# :field2 => :pointer,
|
246
|
+
# :field3 => :string
|
247
|
+
# end
|
248
|
+
# @note Creating a layout from a hash +spec+ is supported only for Ruby 1.9.
|
185
249
|
def layout(*spec)
|
186
250
|
# raise RuntimeError, "struct layout already defined for #{self.inspect}" if defined?(@layout)
|
187
251
|
return @layout if spec.size == 0
|
@@ -254,6 +318,11 @@ module FFI
|
|
254
318
|
|
255
319
|
private
|
256
320
|
|
321
|
+
# @param [StructLayoutBuilder] builder
|
322
|
+
# @param [Hash] spec
|
323
|
+
# @return [builder]
|
324
|
+
# @raise if Ruby 1.8
|
325
|
+
# Add hash +spec+ to +builder+.
|
257
326
|
def hash_layout(builder, spec)
|
258
327
|
raise "Ruby version not supported" if RUBY_VERSION =~ /1.8.*/
|
259
328
|
spec[0].each do |name, type|
|
@@ -261,6 +330,10 @@ module FFI
|
|
261
330
|
end
|
262
331
|
end
|
263
332
|
|
333
|
+
# @param [StructLayoutBuilder] builder
|
334
|
+
# @param [Array<Symbol, Integer>] spec
|
335
|
+
# @return [builder]
|
336
|
+
# Add array +spec+ to +builder+.
|
264
337
|
def array_layout(builder, spec)
|
265
338
|
i = 0
|
266
339
|
while i < spec.size
|
@@ -19,8 +19,11 @@
|
|
19
19
|
#
|
20
20
|
|
21
21
|
module FFI
|
22
|
+
|
23
|
+
# Build a {StructLayout struct layout}.
|
22
24
|
class StructLayoutBuilder
|
23
|
-
attr_reader :size
|
25
|
+
attr_reader :size
|
26
|
+
attr_reader :alignment
|
24
27
|
|
25
28
|
def initialize
|
26
29
|
@size = 0
|
@@ -31,23 +34,42 @@ module FFI
|
|
31
34
|
@fields = Array.new
|
32
35
|
end
|
33
36
|
|
37
|
+
# @param [Numeric] size
|
38
|
+
# Set size attribute with +size+ only if +size+ is greater than attribute value.
|
34
39
|
def size=(size)
|
35
40
|
@size = size if size > @size
|
36
41
|
end
|
37
42
|
|
43
|
+
# @param [Numeric] alignment
|
44
|
+
# Set alignment attribute with +alignment+ only if it is greater than attribute value.
|
38
45
|
def alignment=(align)
|
39
46
|
@alignment = align if align > @alignment
|
40
47
|
@min_alignment = align
|
41
48
|
end
|
42
49
|
|
50
|
+
# @param [Boolean] is_union
|
51
|
+
# @return [is_union]
|
52
|
+
# Set union attribute.
|
53
|
+
# Set to +true+ to build a {Union} instead of a {Struct}.
|
43
54
|
def union=(is_union)
|
44
55
|
@union = is_union
|
45
56
|
end
|
46
57
|
|
58
|
+
# @return [Boolean]
|
59
|
+
# Building a {Union} or a {Struct} ?
|
47
60
|
def union?
|
48
61
|
@union
|
49
62
|
end
|
50
63
|
|
64
|
+
# Set packed attribute
|
65
|
+
# @overload packed=(packed)
|
66
|
+
# @param [Fixnum] packed
|
67
|
+
# @return [packed]
|
68
|
+
# Set alignment and packed attributes to +packed+.
|
69
|
+
# @overload packed=(packed)
|
70
|
+
# @param packed
|
71
|
+
# @return [0,1]
|
72
|
+
# Set packed attribute.
|
51
73
|
def packed=(packed)
|
52
74
|
if packed.is_a?(Fixnum)
|
53
75
|
@alignment = packed
|
@@ -58,6 +80,7 @@ module FFI
|
|
58
80
|
end
|
59
81
|
|
60
82
|
|
83
|
+
# List of number types
|
61
84
|
NUMBER_TYPES = [
|
62
85
|
Type::INT8,
|
63
86
|
Type::UINT8,
|
@@ -75,6 +98,12 @@ module FFI
|
|
75
98
|
Type::BOOL,
|
76
99
|
]
|
77
100
|
|
101
|
+
# @param [String, Symbol] name name of the field
|
102
|
+
# @param [Array, DataConverter, Struct, StructLayout::Field, Symbol, Type] type type of the field
|
103
|
+
# @param [Numeric, nil] offset
|
104
|
+
# @return [self]
|
105
|
+
# Add a field to the builder.
|
106
|
+
# @note Setting +offset+ to +nil+ or +-1+ is equivalent to +0+.
|
78
107
|
def add(name, type, offset = nil)
|
79
108
|
|
80
109
|
if offset.nil? || offset == -1
|
@@ -92,18 +121,33 @@ module FFI
|
|
92
121
|
return self
|
93
122
|
end
|
94
123
|
|
124
|
+
# @param (see #add)
|
125
|
+
# @return (see #add)
|
126
|
+
# Same as {#add}.
|
127
|
+
# @see #add
|
95
128
|
def add_field(name, type, offset = nil)
|
96
129
|
add(name, type, offset)
|
97
130
|
end
|
98
131
|
|
132
|
+
# @param (see #add)
|
133
|
+
# @return (see #add)
|
134
|
+
# Add a struct as a field to the builder.
|
99
135
|
def add_struct(name, type, offset = nil)
|
100
136
|
add(name, Type::Struct.new(type), offset)
|
101
137
|
end
|
102
138
|
|
139
|
+
# @param name (see #add)
|
140
|
+
# @param type (see #add)
|
141
|
+
# @param [Numeric] count array length
|
142
|
+
# @param offset (see #add)
|
143
|
+
# @return (see #add)
|
144
|
+
# Add an array as a field to the builder.
|
103
145
|
def add_array(name, type, count, offset = nil)
|
104
146
|
add(name, Type::Array.new(type, count), offset)
|
105
147
|
end
|
106
148
|
|
149
|
+
# @return [StructLayout]
|
150
|
+
# Build and return the struct layout.
|
107
151
|
def build
|
108
152
|
# Add tail padding if the struct is not packed
|
109
153
|
size = @packed ? @size : align(@size, @alignment)
|
@@ -115,10 +159,15 @@ module FFI
|
|
115
159
|
|
116
160
|
private
|
117
161
|
|
162
|
+
# @param [Numeric] offset
|
163
|
+
# @param [Numeric] align
|
164
|
+
# @return [Numeric]
|
118
165
|
def align(offset, align)
|
119
166
|
align + ((offset - 1) & ~(align - 1));
|
120
167
|
end
|
121
168
|
|
169
|
+
# @param (see #add)
|
170
|
+
# @return [StructLayout::Field]
|
122
171
|
def field_for_type(name, offset, type)
|
123
172
|
field_class = case
|
124
173
|
when type.is_a?(Type::Function)
|
data/lib/ffi/tools/generator.rb
CHANGED
data/libtest/Benchmark.c
CHANGED
@@ -1,21 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* Copyright (c) 2007 Wayne Meissner. All rights reserved.
|
3
3
|
*
|
4
|
-
*
|
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/>.
|
4
|
+
* For licensing, see LICENSE.SPECS
|
19
5
|
*/
|
20
6
|
#include <sys/types.h>
|
21
7
|
#include <stdint.h>
|
data/libtest/BoolTest.c
CHANGED
@@ -1,21 +1,7 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c)
|
3
|
-
*
|
4
|
-
* All rights reserved.
|
2
|
+
* Copyright (c) 2007 Wayne Meissner. All rights reserved.
|
5
3
|
*
|
6
|
-
*
|
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/>.
|
4
|
+
* For licensing, see LICENSE.SPECS
|
19
5
|
*/
|
20
6
|
|
21
7
|
#include <stdbool.h>
|
data/libtest/BufferTest.c
CHANGED
@@ -1,21 +1,7 @@
|
|
1
|
-
/*
|
2
|
-
* Copyright (
|
3
|
-
*
|
4
|
-
* All rights reserved.
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2007 Wayne Meissner. All rights reserved.
|
5
3
|
*
|
6
|
-
*
|
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/>.
|
4
|
+
* For licensing, see LICENSE.SPECS
|
19
5
|
*/
|
20
6
|
|
21
7
|
|
data/libtest/ClosureTest.c
CHANGED
@@ -1,21 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* Copyright (c) 2007 Wayne Meissner. All rights reserved.
|
3
|
-
*
|
4
|
-
* All rights reserved.
|
5
3
|
*
|
6
|
-
*
|
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/>.
|
4
|
+
* For licensing, see LICENSE.SPECS
|
19
5
|
*/
|
20
6
|
|
21
7
|
#include <stdlib.h>
|
data/libtest/EnumTest.c
CHANGED
@@ -1,21 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* Copyright (c) 2007 Wayne Meissner. All rights reserved.
|
3
3
|
*
|
4
|
-
*
|
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/>.
|
4
|
+
* For licensing, see LICENSE.SPECS
|
19
5
|
*/
|
20
6
|
|
21
7
|
int test_untagged_enum(int val) {
|