ffi 0.3.5 → 0.4.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.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/README.rdoc +51 -1
- data/Rakefile +34 -26
- data/ext/ffi_c/AbstractMemory.c +73 -70
- data/ext/ffi_c/AbstractMemory.h +8 -4
- data/ext/ffi_c/AutoPointer.c +8 -9
- data/ext/ffi_c/AutoPointer.h +2 -2
- data/ext/ffi_c/Buffer.c +19 -20
- data/ext/ffi_c/Callback.c +85 -33
- data/ext/ffi_c/Callback.h +11 -5
- data/ext/ffi_c/{NativeLibrary.c → DynamicLibrary.c} +83 -16
- data/ext/ffi_c/{NativeLibrary.h → DynamicLibrary.h} +1 -1
- data/ext/ffi_c/Invoker.c +148 -192
- data/ext/ffi_c/LastError.c +135 -0
- data/ext/ffi_c/LastError.h +18 -0
- data/ext/ffi_c/MemoryPointer.c +26 -19
- data/ext/ffi_c/MemoryPointer.h +3 -3
- data/ext/ffi_c/NullPointer.c +49 -47
- data/ext/ffi_c/Platform.c +9 -10
- data/ext/ffi_c/Platform.h +1 -1
- data/ext/ffi_c/Pointer.c +52 -21
- data/ext/ffi_c/Pointer.h +8 -6
- data/ext/ffi_c/Struct.c +70 -61
- data/ext/ffi_c/Struct.h +2 -2
- data/ext/ffi_c/Type.c +230 -0
- data/ext/ffi_c/Type.h +28 -0
- data/ext/ffi_c/Types.c +47 -6
- data/ext/ffi_c/Types.h +8 -2
- data/ext/ffi_c/endian.h +40 -0
- data/ext/ffi_c/extconf.rb +6 -5
- data/ext/ffi_c/ffi.c +20 -43
- data/ext/ffi_c/libffi.bsd.mk +34 -0
- data/ext/ffi_c/libffi.darwin.mk +30 -10
- data/ext/ffi_c/libffi.gnu.mk +29 -0
- data/ext/ffi_c/libffi.mk +4 -2
- data/ext/ffi_c/rbffi.h +6 -8
- data/lib/ffi.rb +10 -1
- data/lib/ffi/autopointer.rb +1 -1
- data/lib/ffi/enum.rb +78 -0
- data/lib/ffi/ffi.rb +5 -6
- data/lib/ffi/io.rb +15 -1
- data/lib/ffi/library.rb +78 -17
- data/lib/ffi/pointer.rb +2 -2
- data/lib/ffi/struct.rb +68 -14
- data/lib/ffi/types.rb +6 -3
- data/lib/ffi/variadic.rb +2 -2
- data/spec/ffi/bool_spec.rb +24 -0
- data/spec/ffi/callback_spec.rb +217 -17
- data/spec/ffi/enum_spec.rb +164 -0
- data/spec/ffi/managed_struct_spec.rb +6 -1
- data/spec/ffi/number_spec.rb +30 -0
- data/spec/ffi/pointer_spec.rb +33 -8
- data/spec/ffi/rbx/memory_pointer_spec.rb +0 -6
- data/spec/ffi/spec_helper.rb +5 -1
- data/spec/ffi/string_spec.rb +65 -4
- data/spec/ffi/struct_callback_spec.rb +41 -0
- data/spec/ffi/struct_initialize_spec.rb +30 -0
- data/spec/ffi/struct_spec.rb +19 -20
- metadata +29 -52
- data/ext/ffi_c/ffi.mk +0 -23
data/lib/ffi/types.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module FFI
|
2
2
|
# TypeDefs = Hash.new
|
3
3
|
def self.add_typedef(current, add)
|
4
|
-
if current.kind_of?
|
4
|
+
if current.kind_of?(FFI::Type)
|
5
5
|
code = current
|
6
6
|
else
|
7
7
|
code = TypeDefs[current]
|
@@ -13,8 +13,7 @@ module FFI
|
|
13
13
|
def self.find_type(name, type_map = nil)
|
14
14
|
type_map = TypeDefs if type_map.nil?
|
15
15
|
code = type_map[name]
|
16
|
-
code = name if !code && name.kind_of?(
|
17
|
-
code = name if !code && name.kind_of?(FFI::CallbackInfo)
|
16
|
+
code = name if !code && name.kind_of?(FFI::Type)
|
18
17
|
raise TypeError, "Unable to resolve type '#{name}'" unless code
|
19
18
|
return code
|
20
19
|
end
|
@@ -92,7 +91,11 @@ module FFI
|
|
92
91
|
add_typedef(NativeType::BUFFER_IN, :buffer_in)
|
93
92
|
add_typedef(NativeType::BUFFER_OUT, :buffer_out)
|
94
93
|
add_typedef(NativeType::BUFFER_INOUT, :buffer_inout)
|
94
|
+
|
95
95
|
add_typedef(NativeType::VARARGS, :varargs)
|
96
|
+
|
97
|
+
add_typedef(NativeType::ENUM, :enum)
|
98
|
+
add_typedef(NativeType::BOOL, :bool)
|
96
99
|
|
97
100
|
# Use for a C struct with a char [] embedded inside.
|
98
101
|
add_typedef(NativeType::CHAR_ARRAY, :char_array)
|
data/lib/ffi/variadic.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module FFI
|
2
2
|
class VariadicInvoker
|
3
|
-
def VariadicInvoker.new(
|
4
|
-
invoker = self.__new(
|
3
|
+
def VariadicInvoker.new(function, arg_types, rb_ret_type, ret_type, options)
|
4
|
+
invoker = self.__new(function, rb_ret_type, ret_type, options[:convention].to_s, options[:enums])
|
5
5
|
invoker.init(arg_types, options[:type_map])
|
6
6
|
invoker
|
7
7
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
describe "Function with primitive boolean arguments and return values" do
|
3
|
+
module LibTest
|
4
|
+
extend FFI::Library
|
5
|
+
ffi_lib TestLibrary::PATH
|
6
|
+
attach_function :bool_return_true, [ ], :bool
|
7
|
+
attach_function :bool_return_false, [ ], :bool
|
8
|
+
attach_function :bool_return_val, [ :bool ], :bool
|
9
|
+
attach_function :bool_reverse_val, [ :bool ], :bool
|
10
|
+
end
|
11
|
+
it "bools" do
|
12
|
+
LibTest.bool_return_true.should == true
|
13
|
+
LibTest.bool_return_false.should == false
|
14
|
+
|
15
|
+
LibTest.bool_return_val(true).should == true
|
16
|
+
LibTest.bool_return_val(false).should == false
|
17
|
+
|
18
|
+
LibTest.bool_reverse_val(true).should == false
|
19
|
+
LibTest.bool_reverse_val(false).should == true
|
20
|
+
end
|
21
|
+
it "raise error on invalid types" do
|
22
|
+
lambda { LibTest.bool_return_val(nil) }.should raise_error(::TypeError)
|
23
|
+
end
|
24
|
+
end
|
data/spec/ffi/callback_spec.rb
CHANGED
@@ -37,21 +37,30 @@ describe "Callback" do
|
|
37
37
|
callback :cbVrU16, [ ], :ushort
|
38
38
|
callback :cbVrS32, [ ], :int
|
39
39
|
callback :cbVrU32, [ ], :uint
|
40
|
+
callback :cbVrL, [ ], :long
|
41
|
+
callback :cbVrUL, [ ], :ulong
|
40
42
|
callback :cbVrS64, [ ], :long_long
|
41
43
|
callback :cbVrU64, [ ], :ulong_long
|
42
44
|
callback :cbVrP, [], :pointer
|
45
|
+
callback :cbVrZ, [], :bool
|
43
46
|
callback :cbCrV, [ :char ], :void
|
44
47
|
callback :cbSrV, [ :short ], :void
|
45
48
|
callback :cbIrV, [ :int ], :void
|
49
|
+
callback :cbLrV, [ :long ], :void
|
50
|
+
callback :cbULrV, [ :ulong ], :void
|
46
51
|
callback :cbLrV, [ :long_long ], :void
|
52
|
+
|
47
53
|
attach_function :testCallbackVrS8, :testClosureVrB, [ :cbVrS8 ], :char
|
48
54
|
attach_function :testCallbackVrU8, :testClosureVrB, [ :cbVrU8 ], :uchar
|
49
55
|
attach_function :testCallbackVrS16, :testClosureVrS, [ :cbVrS16 ], :short
|
50
56
|
attach_function :testCallbackVrU16, :testClosureVrS, [ :cbVrU16 ], :ushort
|
51
57
|
attach_function :testCallbackVrS32, :testClosureVrI, [ :cbVrS32 ], :int
|
52
58
|
attach_function :testCallbackVrU32, :testClosureVrI, [ :cbVrU32 ], :uint
|
53
|
-
attach_function :
|
54
|
-
attach_function :
|
59
|
+
attach_function :testCallbackVrL, :testClosureVrL, [ :cbVrL ], :long
|
60
|
+
attach_function :testCallbackVrZ, :testClosureVrZ, [ :cbVrZ ], :bool
|
61
|
+
attach_function :testCallbackVrUL, :testClosureVrL, [ :cbVrUL ], :ulong
|
62
|
+
attach_function :testCallbackVrS64, :testClosureVrLL, [ :cbVrS64 ], :long_long
|
63
|
+
attach_function :testCallbackVrU64, :testClosureVrLL, [ :cbVrU64 ], :ulong_long
|
55
64
|
attach_function :testCallbackVrP, :testClosureVrP, [ :cbVrP ], :pointer
|
56
65
|
attach_function :testCallbackCrV, :testClosureBrV, [ :cbCrV, :char ], :void
|
57
66
|
attach_variable :cbVrS8, :gvar_pointer, :cbVrS8
|
@@ -122,7 +131,6 @@ describe "Callback" do
|
|
122
131
|
it "returning :ushort (-1)" do
|
123
132
|
LibTest.testCallbackVrU16 { -1 }.should == 0xffff
|
124
133
|
end
|
125
|
-
|
126
134
|
it "returning :int (0)" do
|
127
135
|
LibTest.testCallbackVrS32 { 0 }.should == 0
|
128
136
|
end
|
@@ -136,7 +144,6 @@ describe "Callback" do
|
|
136
144
|
it "returning :int (-1)" do
|
137
145
|
LibTest.testCallbackVrS32 { -1 }.should == -1
|
138
146
|
end
|
139
|
-
|
140
147
|
it "returning :uint (0)" do
|
141
148
|
LibTest.testCallbackVrU32 { 0 }.should == 0
|
142
149
|
end
|
@@ -153,7 +160,39 @@ describe "Callback" do
|
|
153
160
|
it "Callback returning :uint (-1)" do
|
154
161
|
LibTest.testCallbackVrU32 { -1 }.should == 0xffffffff
|
155
162
|
end
|
156
|
-
|
163
|
+
it "returning :long (0)" do
|
164
|
+
LibTest.testCallbackVrL { 0 }.should == 0
|
165
|
+
end
|
166
|
+
it "returning :long (0x7fffffff)" do
|
167
|
+
LibTest.testCallbackVrL { 0x7fffffff }.should == 0x7fffffff
|
168
|
+
end
|
169
|
+
# test wrap around
|
170
|
+
it "returning :long (-0x80000000)" do
|
171
|
+
LibTest.testCallbackVrL { -0x80000000 }.should == -0x80000000
|
172
|
+
end
|
173
|
+
it "returning :long (-1)" do
|
174
|
+
LibTest.testCallbackVrL { -1 }.should == -1
|
175
|
+
end
|
176
|
+
it "returning :ulong (0)" do
|
177
|
+
LibTest.testCallbackVrUL { 0 }.should == 0
|
178
|
+
end
|
179
|
+
it "returning :ulong (0x7fffffff)" do
|
180
|
+
LibTest.testCallbackVrUL { 0x7fffffff }.should == 0x7fffffff
|
181
|
+
end
|
182
|
+
# test wrap around
|
183
|
+
it "returning :ulong (0x80000000)" do
|
184
|
+
LibTest.testCallbackVrUL { 0x80000000 }.should == 0x80000000
|
185
|
+
end
|
186
|
+
it "returning :ulong (0xffffffff)" do
|
187
|
+
LibTest.testCallbackVrUL { 0xffffffff }.should == 0xffffffff
|
188
|
+
end
|
189
|
+
it "Callback returning :ulong (-1)" do
|
190
|
+
if FFI::Platform::LONG_SIZE == 32
|
191
|
+
LibTest.testCallbackVrUL { -1 }.should == 0xffffffff
|
192
|
+
else
|
193
|
+
LibTest.testCallbackVrUL { -1 }.should == 0xffffffffffffffff
|
194
|
+
end
|
195
|
+
end
|
157
196
|
it "returning :long_long (0)" do
|
158
197
|
LibTest.testCallbackVrS64 { 0 }.should == 0
|
159
198
|
end
|
@@ -167,11 +206,14 @@ describe "Callback" do
|
|
167
206
|
it "returning :long_long (-1)" do
|
168
207
|
LibTest.testCallbackVrS64 { -1 }.should == -1
|
169
208
|
end
|
209
|
+
it "returning bool" do
|
210
|
+
LibTest.testCallbackVrZ { true }.should be_true
|
211
|
+
end
|
170
212
|
it "returning :pointer (nil)" do
|
171
213
|
LibTest.testCallbackVrP { nil }.null?.should be_true
|
172
214
|
end
|
173
215
|
it "returning :pointer (MemoryPointer)" do
|
174
|
-
p = MemoryPointer.new :long
|
216
|
+
p = FFI::MemoryPointer.new :long
|
175
217
|
LibTest.testCallbackVrP { p }.should == p
|
176
218
|
end
|
177
219
|
|
@@ -187,6 +229,113 @@ describe "Callback" do
|
|
187
229
|
end
|
188
230
|
end
|
189
231
|
|
232
|
+
describe 'when inlined' do
|
233
|
+
it 'could be anonymous' do
|
234
|
+
module LibTest
|
235
|
+
extend FFI::Library
|
236
|
+
attach_function :testCallbackVrS8, :testClosureVrB, [ callback([ ], :char) ], :char
|
237
|
+
end
|
238
|
+
LibTest.testCallbackVrS8 { 0 }.should == 0
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "as return value" do
|
243
|
+
|
244
|
+
it "should not blow up when a callback is defined that returns a callback" do
|
245
|
+
module LibTest
|
246
|
+
extend FFI::Library
|
247
|
+
callback :cb_return_type_1, [ :short ], :short
|
248
|
+
callback :cb_lookup_1, [ :short ], :cb_return_type_1
|
249
|
+
attach_function :testReturnsCallback_1, :testReturnsClosure, [ :cb_lookup_1, :short ], :cb_return_type_1
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should return a callback" do
|
254
|
+
module LibTest
|
255
|
+
extend FFI::Library
|
256
|
+
callback :cb_return_type, [ :int ], :int
|
257
|
+
callback :cb_lookup, [ ], :cb_return_type
|
258
|
+
attach_function :testReturnsCallback, :testReturnsClosure, [ :cb_lookup, :int ], :int
|
259
|
+
end
|
260
|
+
|
261
|
+
lookup_proc_called = false
|
262
|
+
return_proc_called = false
|
263
|
+
|
264
|
+
return_proc = Proc.new do |a|
|
265
|
+
return_proc_called = true
|
266
|
+
a * 2
|
267
|
+
end
|
268
|
+
lookup_proc = Proc.new do
|
269
|
+
lookup_proc_called = true
|
270
|
+
return_proc
|
271
|
+
end
|
272
|
+
|
273
|
+
val = LibTest.testReturnsCallback(lookup_proc, 0x1234)
|
274
|
+
val.should == 0x1234 * 2
|
275
|
+
lookup_proc_called.should be_true
|
276
|
+
return_proc_called.should be_true
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should return a method callback" do
|
280
|
+
module LibTest
|
281
|
+
extend FFI::Library
|
282
|
+
callback :cb_return_type, [ :int ], :int
|
283
|
+
callback :cb_lookup, [ ], :cb_return_type
|
284
|
+
attach_function :testReturnsCallback, :testReturnsClosure, [ :cb_lookup, :int ], :int
|
285
|
+
end
|
286
|
+
module MethodCallback
|
287
|
+
def self.lookup
|
288
|
+
method(:perform)
|
289
|
+
end
|
290
|
+
def self.perform num
|
291
|
+
num * 2
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
LibTest.testReturnsCallback(MethodCallback.method(:lookup), 0x1234).should == 0x2468
|
296
|
+
end
|
297
|
+
|
298
|
+
it 'should not blow up when a callback takes a callback as argument' do
|
299
|
+
module LibTest
|
300
|
+
extend FFI::Library
|
301
|
+
callback :cb_argument, [ :int ], :int
|
302
|
+
callback :cb_with_cb_argument, [ :cb_argument, :int ], :int
|
303
|
+
attach_function :testCallbackAsArgument, :testArgumentClosure, [ :cb_with_cb_argument, :int ], :int
|
304
|
+
end
|
305
|
+
end
|
306
|
+
it 'should be able to use the callback argument' do
|
307
|
+
module LibTest
|
308
|
+
extend FFI::Library
|
309
|
+
callback :cb_argument, [ :int ], :int
|
310
|
+
callback :cb_with_cb_argument, [ :cb_argument, :int ], :int
|
311
|
+
attach_function :testCallbackAsArgument, :testArgumentClosure, [ :cb_with_cb_argument, :cb_argument, :int ], :int
|
312
|
+
end
|
313
|
+
callback_arg_called = false
|
314
|
+
callback_with_callback_arg_called = false
|
315
|
+
callback_arg = Proc.new do |val|
|
316
|
+
callback_arg_called = true
|
317
|
+
val * 2
|
318
|
+
end
|
319
|
+
callback_with_callback_arg = Proc.new do |cb, val|
|
320
|
+
callback_with_callback_arg_called = true
|
321
|
+
cb.call(val)
|
322
|
+
end
|
323
|
+
val = LibTest.testCallbackAsArgument(callback_with_callback_arg, callback_arg, 0xff1)
|
324
|
+
val.should == 0xff1 * 2
|
325
|
+
callback_arg_called.should be_true
|
326
|
+
callback_with_callback_arg_called.should be_true
|
327
|
+
end
|
328
|
+
it 'function returns callable object' do
|
329
|
+
module LibTest
|
330
|
+
extend FFI::Library
|
331
|
+
callback :funcptr, [ :int ], :int
|
332
|
+
attach_function :testReturnsFunctionPointer, [ ], :funcptr
|
333
|
+
end
|
334
|
+
f = LibTest.testReturnsFunctionPointer
|
335
|
+
f.call(3).should == 6
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
190
339
|
end
|
191
340
|
describe "primitive argument" do
|
192
341
|
#
|
@@ -199,16 +348,27 @@ describe "primitive argument" do
|
|
199
348
|
callback :cbU8rV, [ :uchar ], :void
|
200
349
|
callback :cbS16rV, [ :short ], :void
|
201
350
|
callback :cbU16rV, [ :ushort ], :void
|
351
|
+
|
352
|
+
callback :cbZrV, [ :bool ], :void
|
202
353
|
callback :cbS32rV, [ :int ], :void
|
203
354
|
callback :cbU32rV, [ :uint ], :void
|
355
|
+
|
356
|
+
callback :cbLrV, [ :long ], :void
|
357
|
+
callback :cbULrV, [ :ulong ], :void
|
358
|
+
|
204
359
|
callback :cbS64rV, [ :long_long ], :void
|
205
360
|
attach_function :testCallbackCrV, :testClosureBrV, [ :cbS8rV, :char ], :void
|
206
361
|
attach_function :testCallbackU8rV, :testClosureBrV, [ :cbU8rV, :uchar ], :void
|
207
362
|
attach_function :testCallbackSrV, :testClosureSrV, [ :cbS16rV, :short ], :void
|
208
363
|
attach_function :testCallbackU16rV, :testClosureSrV, [ :cbU16rV, :ushort ], :void
|
364
|
+
attach_function :testCallbackZrV, :testClosureZrV, [ :cbZrV, :bool ], :void
|
209
365
|
attach_function :testCallbackIrV, :testClosureIrV, [ :cbS32rV, :int ], :void
|
210
366
|
attach_function :testCallbackU32rV, :testClosureIrV, [ :cbU32rV, :uint ], :void
|
211
|
-
|
367
|
+
|
368
|
+
attach_function :testCallbackLrV, :testClosureLrV, [ :cbLrV, :long ], :void
|
369
|
+
attach_function :testCallbackULrV, :testClosureULrV, [ :cbULrV, :ulong ], :void
|
370
|
+
|
371
|
+
attach_function :testCallbackLLrV, :testClosureLLrV, [ :cbS64rV, :long_long ], :void
|
212
372
|
end
|
213
373
|
it ":char (0) argument" do
|
214
374
|
v = 0xdeadbeef
|
@@ -230,7 +390,6 @@ describe "primitive argument" do
|
|
230
390
|
LibTest.testCallbackCrV(-1) { |i| v = i }
|
231
391
|
v.should == -1
|
232
392
|
end
|
233
|
-
|
234
393
|
it ":uchar (0) argument" do
|
235
394
|
v = 0xdeadbeef
|
236
395
|
LibTest.testCallbackU8rV(0) { |i| v = i }
|
@@ -272,7 +431,6 @@ describe "primitive argument" do
|
|
272
431
|
LibTest.testCallbackSrV(-1) { |i| v = i }
|
273
432
|
v.should == -1
|
274
433
|
end
|
275
|
-
|
276
434
|
it ":ushort (0) argument" do
|
277
435
|
v = 0xdeadbeef
|
278
436
|
LibTest.testCallbackU16rV(0) { |i| v = i }
|
@@ -293,7 +451,11 @@ describe "primitive argument" do
|
|
293
451
|
LibTest.testCallbackU16rV(0xffff) { |i| v = i }
|
294
452
|
v.should == 0xffff
|
295
453
|
end
|
296
|
-
|
454
|
+
it ":bool (true) argument" do
|
455
|
+
v = false
|
456
|
+
LibTest.testCallbackZrV(true) { |i| v = i }
|
457
|
+
v.should be_true
|
458
|
+
end
|
297
459
|
it ":int (0) argument" do
|
298
460
|
v = 0xdeadbeef
|
299
461
|
LibTest.testCallbackIrV(0) { |i| v = i }
|
@@ -314,7 +476,6 @@ describe "primitive argument" do
|
|
314
476
|
LibTest.testCallbackIrV(-1) { |i| v = i }
|
315
477
|
v.should == -1
|
316
478
|
end
|
317
|
-
|
318
479
|
it ":uint (0) argument" do
|
319
480
|
v = 0xdeadbeef
|
320
481
|
LibTest.testCallbackU32rV(0) { |i| v = i }
|
@@ -335,26 +496,65 @@ describe "primitive argument" do
|
|
335
496
|
LibTest.testCallbackU32rV(0xffffffff) { |i| v = i }
|
336
497
|
v.should == 0xffffffff
|
337
498
|
end
|
338
|
-
|
339
|
-
it ":long_long (0) argument" do
|
499
|
+
it ":long (0) argument" do
|
340
500
|
v = 0xdeadbeef
|
341
501
|
LibTest.testCallbackLrV(0) { |i| v = i }
|
342
502
|
v.should == 0
|
343
503
|
end
|
504
|
+
it ":long (0x7fffffff) argument" do
|
505
|
+
v = 0xdeadbeef
|
506
|
+
LibTest.testCallbackLrV(0x7fffffff) { |i| v = i }
|
507
|
+
v.should == 0x7fffffff
|
508
|
+
end
|
509
|
+
it ":long (-0x80000000) argument" do
|
510
|
+
v = 0xdeadbeef
|
511
|
+
LibTest.testCallbackLrV(-0x80000000) { |i| v = i }
|
512
|
+
v.should == -0x80000000
|
513
|
+
end
|
514
|
+
it ":long (-1) argument" do
|
515
|
+
v = 0xdeadbeef
|
516
|
+
LibTest.testCallbackLrV(-1) { |i| v = i }
|
517
|
+
v.should == -1
|
518
|
+
end
|
519
|
+
it ":ulong (0) argument" do
|
520
|
+
v = 0xdeadbeef
|
521
|
+
LibTest.testCallbackULrV(0) { |i| v = i }
|
522
|
+
v.should == 0
|
523
|
+
end
|
524
|
+
it ":ulong (0x7fffffff) argument" do
|
525
|
+
v = 0xdeadbeef
|
526
|
+
LibTest.testCallbackULrV(0x7fffffff) { |i| v = i }
|
527
|
+
v.should == 0x7fffffff
|
528
|
+
end
|
529
|
+
it ":ulong (0x80000000) argument" do
|
530
|
+
v = 0xdeadbeef
|
531
|
+
LibTest.testCallbackULrV(0x80000000) { |i| v = i }
|
532
|
+
v.should == 0x80000000
|
533
|
+
end
|
534
|
+
it ":ulong (0xffffffff) argument" do
|
535
|
+
v = 0xdeadbeef
|
536
|
+
LibTest.testCallbackULrV(0xffffffff) { |i| v = i }
|
537
|
+
v.should == 0xffffffff
|
538
|
+
end
|
539
|
+
it ":long_long (0) argument" do
|
540
|
+
v = 0xdeadbeef
|
541
|
+
LibTest.testCallbackLLrV(0) { |i| v = i }
|
542
|
+
v.should == 0
|
543
|
+
end
|
344
544
|
it ":long_long (0x7fffffffffffffff) argument" do
|
345
545
|
v = 0xdeadbeef
|
346
|
-
LibTest.
|
546
|
+
LibTest.testCallbackLLrV(0x7fffffffffffffff) { |i| v = i }
|
347
547
|
v.should == 0x7fffffffffffffff
|
348
548
|
end
|
349
549
|
it ":long_long (-0x8000000000000000) argument" do
|
350
550
|
v = 0xdeadbeef
|
351
|
-
LibTest.
|
551
|
+
LibTest.testCallbackLLrV(-0x8000000000000000) { |i| v = i }
|
352
552
|
v.should == -0x8000000000000000
|
353
553
|
end
|
354
554
|
it ":long_long (-1) argument" do
|
355
555
|
v = 0xdeadbeef
|
356
|
-
LibTest.
|
556
|
+
LibTest.testCallbackLLrV(-1) { |i| v = i }
|
357
557
|
v.should == -1
|
358
558
|
end
|
359
559
|
|
360
|
-
end unless true
|
560
|
+
end # unless true
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
module TestEnum0
|
4
|
+
extend FFI::Library
|
5
|
+
end
|
6
|
+
|
7
|
+
module TestEnum1
|
8
|
+
extend FFI::Library
|
9
|
+
ffi_lib TestLibrary::PATH
|
10
|
+
|
11
|
+
enum [:c1, :c2, :c3, :c4]
|
12
|
+
enum [:c5, 42, :c6, :c7, :c8]
|
13
|
+
enum [:c9, 42, :c10, :c11, 4242, :c12]
|
14
|
+
enum [:c13, 42, :c14, 4242, :c15, 424242, :c16, 42424242]
|
15
|
+
|
16
|
+
attach_function :test_untagged_enum, [:int], :int
|
17
|
+
end
|
18
|
+
|
19
|
+
module TestEnum3
|
20
|
+
extend FFI::Library
|
21
|
+
ffi_lib TestLibrary::PATH
|
22
|
+
|
23
|
+
enum :enum_type1, [:c1, :c2, :c3, :c4]
|
24
|
+
enum :enum_type2, [:c5, 42, :c6, :c7, :c8]
|
25
|
+
enum :enum_type3, [:c9, 42, :c10, :c11, 4242, :c12]
|
26
|
+
enum :enum_type4, [:c13, 42, :c14, 4242, :c15, 424242, :c16, 42424242]
|
27
|
+
|
28
|
+
attach_function :test_tagged_typedef_enum1, [:enum_type1], :enum_type1
|
29
|
+
attach_function :test_tagged_typedef_enum2, [:enum_type2], :enum_type2
|
30
|
+
attach_function :test_tagged_typedef_enum3, [:enum_type3], :enum_type3
|
31
|
+
attach_function :test_tagged_typedef_enum4, [:enum_type4], :enum_type4
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "A library with no enum defined" do
|
35
|
+
it "returns nil when asked for an enum" do
|
36
|
+
TestEnum0.enum_type(:foo).should == nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "An untagged enum" do
|
41
|
+
it "constants can be used as function parameters and return value" do
|
42
|
+
TestEnum1.test_untagged_enum(:c1).should == 0
|
43
|
+
TestEnum1.test_untagged_enum(:c2).should == 1
|
44
|
+
TestEnum1.test_untagged_enum(:c3).should == 2
|
45
|
+
TestEnum1.test_untagged_enum(:c4).should == 3
|
46
|
+
TestEnum1.test_untagged_enum(:c5).should == 42
|
47
|
+
TestEnum1.test_untagged_enum(:c6).should == 43
|
48
|
+
TestEnum1.test_untagged_enum(:c7).should == 44
|
49
|
+
TestEnum1.test_untagged_enum(:c8).should == 45
|
50
|
+
TestEnum1.test_untagged_enum(:c9).should == 42
|
51
|
+
TestEnum1.test_untagged_enum(:c10).should == 43
|
52
|
+
TestEnum1.test_untagged_enum(:c11).should == 4242
|
53
|
+
TestEnum1.test_untagged_enum(:c12).should == 4243
|
54
|
+
TestEnum1.test_untagged_enum(:c13).should == 42
|
55
|
+
TestEnum1.test_untagged_enum(:c14).should == 4242
|
56
|
+
TestEnum1.test_untagged_enum(:c15).should == 424242
|
57
|
+
TestEnum1.test_untagged_enum(:c16).should == 42424242
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "A tagged typedef enum" do
|
62
|
+
it "is accessible through its tag" do
|
63
|
+
TestEnum3.enum_type(:enum_type1).should_not == nil
|
64
|
+
TestEnum3.enum_type(:enum_type2).should_not == nil
|
65
|
+
TestEnum3.enum_type(:enum_type3).should_not == nil
|
66
|
+
TestEnum3.enum_type(:enum_type4).should_not == nil
|
67
|
+
end
|
68
|
+
it "contains enum constants" do
|
69
|
+
TestEnum3.enum_type(:enum_type1).symbols.length.should == 4
|
70
|
+
TestEnum3.enum_type(:enum_type2).symbols.length.should == 4
|
71
|
+
TestEnum3.enum_type(:enum_type3).symbols.length.should == 4
|
72
|
+
TestEnum3.enum_type(:enum_type4).symbols.length.should == 4
|
73
|
+
end
|
74
|
+
it "constants can be used as function parameters and return value" do
|
75
|
+
TestEnum3.test_tagged_typedef_enum1(:c1).should == :c1
|
76
|
+
TestEnum3.test_tagged_typedef_enum1(:c2).should == :c2
|
77
|
+
TestEnum3.test_tagged_typedef_enum1(:c3).should == :c3
|
78
|
+
TestEnum3.test_tagged_typedef_enum1(:c4).should == :c4
|
79
|
+
TestEnum3.test_tagged_typedef_enum2(:c5).should == :c5
|
80
|
+
TestEnum3.test_tagged_typedef_enum2(:c6).should == :c6
|
81
|
+
TestEnum3.test_tagged_typedef_enum2(:c7).should == :c7
|
82
|
+
TestEnum3.test_tagged_typedef_enum2(:c8).should == :c8
|
83
|
+
TestEnum3.test_tagged_typedef_enum3(:c9).should == :c9
|
84
|
+
TestEnum3.test_tagged_typedef_enum3(:c10).should == :c10
|
85
|
+
TestEnum3.test_tagged_typedef_enum3(:c11).should == :c11
|
86
|
+
TestEnum3.test_tagged_typedef_enum3(:c12).should == :c12
|
87
|
+
TestEnum3.test_tagged_typedef_enum4(:c13).should == :c13
|
88
|
+
TestEnum3.test_tagged_typedef_enum4(:c14).should == :c14
|
89
|
+
TestEnum3.test_tagged_typedef_enum4(:c15).should == :c15
|
90
|
+
TestEnum3.test_tagged_typedef_enum4(:c16).should == :c16
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "All enums" do
|
95
|
+
it "have autonumbered constants when defined with names only" do
|
96
|
+
TestEnum1.enum_value(:c1).should == 0
|
97
|
+
TestEnum1.enum_value(:c2).should == 1
|
98
|
+
TestEnum1.enum_value(:c3).should == 2
|
99
|
+
TestEnum1.enum_value(:c4).should == 3
|
100
|
+
|
101
|
+
TestEnum3.enum_value(:c1).should == 0
|
102
|
+
TestEnum3.enum_value(:c2).should == 1
|
103
|
+
TestEnum3.enum_value(:c3).should == 2
|
104
|
+
TestEnum3.enum_value(:c4).should == 3
|
105
|
+
end
|
106
|
+
it "can have an explicit first constant and autonumbered subsequent constants" do
|
107
|
+
TestEnum1.enum_value(:c5).should == 42
|
108
|
+
TestEnum1.enum_value(:c6).should == 43
|
109
|
+
TestEnum1.enum_value(:c7).should == 44
|
110
|
+
TestEnum1.enum_value(:c8).should == 45
|
111
|
+
|
112
|
+
TestEnum3.enum_value(:c5).should == 42
|
113
|
+
TestEnum3.enum_value(:c6).should == 43
|
114
|
+
TestEnum3.enum_value(:c7).should == 44
|
115
|
+
TestEnum3.enum_value(:c8).should == 45
|
116
|
+
end
|
117
|
+
it "can have a mix of explicit and autonumbered constants" do
|
118
|
+
TestEnum1.enum_value(:c9).should == 42
|
119
|
+
TestEnum1.enum_value(:c10).should == 43
|
120
|
+
TestEnum1.enum_value(:c11).should == 4242
|
121
|
+
TestEnum1.enum_value(:c12).should == 4243
|
122
|
+
|
123
|
+
TestEnum3.enum_value(:c9).should == 42
|
124
|
+
TestEnum3.enum_value(:c10).should == 43
|
125
|
+
TestEnum3.enum_value(:c11).should == 4242
|
126
|
+
TestEnum3.enum_value(:c12).should == 4243
|
127
|
+
end
|
128
|
+
it "can have all its constants explicitely valued" do
|
129
|
+
TestEnum1.enum_value(:c13).should == 42
|
130
|
+
TestEnum1.enum_value(:c14).should == 4242
|
131
|
+
TestEnum1.enum_value(:c15).should == 424242
|
132
|
+
TestEnum1.enum_value(:c16).should == 42424242
|
133
|
+
|
134
|
+
TestEnum3.enum_value(:c13).should == 42
|
135
|
+
TestEnum3.enum_value(:c14).should == 4242
|
136
|
+
TestEnum3.enum_value(:c15).should == 424242
|
137
|
+
TestEnum3.enum_value(:c16).should == 42424242
|
138
|
+
end
|
139
|
+
it "return the constant corresponding to a specific value" do
|
140
|
+
enum = TestEnum3.enum_type(:enum_type1)
|
141
|
+
enum[0].should == :c1
|
142
|
+
enum[1].should == :c2
|
143
|
+
enum[2].should == :c3
|
144
|
+
enum[3].should == :c4
|
145
|
+
|
146
|
+
enum = TestEnum3.enum_type(:enum_type2)
|
147
|
+
enum[42].should == :c5
|
148
|
+
enum[43].should == :c6
|
149
|
+
enum[44].should == :c7
|
150
|
+
enum[45].should == :c8
|
151
|
+
|
152
|
+
enum = TestEnum3.enum_type(:enum_type3)
|
153
|
+
enum[42].should == :c9
|
154
|
+
enum[43].should == :c10
|
155
|
+
enum[4242].should == :c11
|
156
|
+
enum[4243].should == :c12
|
157
|
+
|
158
|
+
enum = TestEnum3.enum_type(:enum_type4)
|
159
|
+
enum[42].should == :c13
|
160
|
+
enum[4242].should == :c14
|
161
|
+
enum[424242].should == :c15
|
162
|
+
enum[42424242].should == :c16
|
163
|
+
end
|
164
|
+
end
|