ffi 0.4.0 → 0.5.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.rdoc +15 -15
- data/Rakefile +57 -8
- data/ext/ffi_c/AbstractMemory.c +101 -24
- data/ext/ffi_c/AbstractMemory.h +98 -6
- data/ext/ffi_c/ArrayType.c +129 -0
- data/ext/ffi_c/ArrayType.h +58 -0
- data/ext/ffi_c/AutoPointer.c +1 -0
- data/ext/ffi_c/Buffer.c +59 -43
- data/ext/ffi_c/Call.c +853 -0
- data/ext/ffi_c/Call.h +86 -0
- data/ext/ffi_c/ClosurePool.c +302 -0
- data/ext/ffi_c/ClosurePool.h +29 -0
- data/ext/ffi_c/DynamicLibrary.c +3 -0
- data/ext/ffi_c/Function.c +478 -0
- data/ext/ffi_c/Function.h +80 -0
- data/ext/ffi_c/FunctionInfo.c +221 -0
- data/ext/ffi_c/LastError.c +30 -6
- data/ext/ffi_c/MemoryPointer.c +50 -28
- data/ext/ffi_c/MethodHandle.c +346 -0
- data/ext/ffi_c/MethodHandle.h +53 -0
- data/ext/ffi_c/Pointer.c +73 -13
- data/ext/ffi_c/Pointer.h +31 -7
- data/ext/ffi_c/Struct.c +517 -224
- data/ext/ffi_c/Struct.h +60 -6
- data/ext/ffi_c/StructByValue.c +140 -0
- data/ext/ffi_c/StructByValue.h +53 -0
- data/ext/ffi_c/StructLayout.c +450 -0
- data/ext/ffi_c/Type.c +121 -22
- data/ext/ffi_c/Type.h +37 -8
- data/ext/ffi_c/Types.c +46 -61
- data/ext/ffi_c/Types.h +38 -7
- data/ext/ffi_c/Variadic.c +260 -0
- data/ext/ffi_c/compat.h +53 -3
- data/ext/ffi_c/extconf.rb +6 -7
- data/ext/ffi_c/ffi.c +45 -39
- data/ext/ffi_c/libffi.darwin.mk +2 -2
- data/ext/ffi_c/rbffi.h +3 -0
- data/lib/ffi/ffi.rb +7 -4
- data/lib/ffi/library.rb +34 -59
- data/lib/ffi/platform.rb +14 -4
- data/lib/ffi/struct.rb +110 -281
- data/lib/ffi/union.rb +4 -9
- data/lib/ffi/variadic.rb +1 -6
- data/spec/ffi/buffer_spec.rb +6 -0
- data/spec/ffi/callback_spec.rb +34 -3
- data/spec/ffi/function_spec.rb +73 -0
- data/spec/ffi/library_spec.rb +56 -52
- data/spec/ffi/pointer_spec.rb +3 -3
- data/spec/ffi/struct_callback_spec.rb +26 -3
- data/spec/ffi/struct_spec.rb +56 -3
- metadata +42 -11
- data/ext/ffi_c/Callback.c +0 -374
- data/ext/ffi_c/Callback.h +0 -47
- data/ext/ffi_c/Invoker.c +0 -962
- data/ext/ffi_c/NullPointer.c +0 -143
data/lib/ffi/union.rb
CHANGED
@@ -1,17 +1,12 @@
|
|
1
1
|
require 'ffi/struct'
|
2
2
|
|
3
3
|
module FFI
|
4
|
-
|
5
|
-
private
|
6
|
-
def calc_alignment_of(field_class, offset); 0; end
|
7
|
-
def calc_current_size(offset, size)
|
8
|
-
@size = size if size > @size
|
9
|
-
end
|
10
|
-
end
|
4
|
+
|
11
5
|
class Union < FFI::Struct
|
12
|
-
private
|
13
6
|
def self.builder
|
14
|
-
|
7
|
+
b = StructLayoutBuilder.new
|
8
|
+
b.union = true
|
9
|
+
b
|
15
10
|
end
|
16
11
|
end
|
17
12
|
end
|
data/lib/ffi/variadic.rb
CHANGED
@@ -1,10 +1,5 @@
|
|
1
1
|
module FFI
|
2
|
-
class VariadicInvoker
|
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
|
-
invoker.init(arg_types, options[:type_map])
|
6
|
-
invoker
|
7
|
-
end
|
2
|
+
class VariadicInvoker
|
8
3
|
def init(arg_types, type_map)
|
9
4
|
@fixed = Array.new
|
10
5
|
@type_map = type_map
|
data/spec/ffi/buffer_spec.rb
CHANGED
data/spec/ffi/callback_spec.rb
CHANGED
@@ -157,7 +157,7 @@ describe "Callback" do
|
|
157
157
|
it "returning :uint (0xffffffff)" do
|
158
158
|
LibTest.testCallbackVrU32 { 0xffffffff }.should == 0xffffffff
|
159
159
|
end
|
160
|
-
it "
|
160
|
+
it "returning :uint (-1)" do
|
161
161
|
LibTest.testCallbackVrU32 { -1 }.should == 0xffffffff
|
162
162
|
end
|
163
163
|
it "returning :long (0)" do
|
@@ -233,6 +233,7 @@ describe "Callback" do
|
|
233
233
|
it 'could be anonymous' do
|
234
234
|
module LibTest
|
235
235
|
extend FFI::Library
|
236
|
+
ffi_lib TestLibrary::PATH
|
236
237
|
attach_function :testCallbackVrS8, :testClosureVrB, [ callback([ ], :char) ], :char
|
237
238
|
end
|
238
239
|
LibTest.testCallbackVrS8 { 0 }.should == 0
|
@@ -244,6 +245,7 @@ describe "Callback" do
|
|
244
245
|
it "should not blow up when a callback is defined that returns a callback" do
|
245
246
|
module LibTest
|
246
247
|
extend FFI::Library
|
248
|
+
ffi_lib TestLibrary::PATH
|
247
249
|
callback :cb_return_type_1, [ :short ], :short
|
248
250
|
callback :cb_lookup_1, [ :short ], :cb_return_type_1
|
249
251
|
attach_function :testReturnsCallback_1, :testReturnsClosure, [ :cb_lookup_1, :short ], :cb_return_type_1
|
@@ -253,6 +255,7 @@ describe "Callback" do
|
|
253
255
|
it "should return a callback" do
|
254
256
|
module LibTest
|
255
257
|
extend FFI::Library
|
258
|
+
ffi_lib TestLibrary::PATH
|
256
259
|
callback :cb_return_type, [ :int ], :int
|
257
260
|
callback :cb_lookup, [ ], :cb_return_type
|
258
261
|
attach_function :testReturnsCallback, :testReturnsClosure, [ :cb_lookup, :int ], :int
|
@@ -279,6 +282,7 @@ describe "Callback" do
|
|
279
282
|
it "should return a method callback" do
|
280
283
|
module LibTest
|
281
284
|
extend FFI::Library
|
285
|
+
ffi_lib TestLibrary::PATH
|
282
286
|
callback :cb_return_type, [ :int ], :int
|
283
287
|
callback :cb_lookup, [ ], :cb_return_type
|
284
288
|
attach_function :testReturnsCallback, :testReturnsClosure, [ :cb_lookup, :int ], :int
|
@@ -298,6 +302,7 @@ describe "Callback" do
|
|
298
302
|
it 'should not blow up when a callback takes a callback as argument' do
|
299
303
|
module LibTest
|
300
304
|
extend FFI::Library
|
305
|
+
ffi_lib TestLibrary::PATH
|
301
306
|
callback :cb_argument, [ :int ], :int
|
302
307
|
callback :cb_with_cb_argument, [ :cb_argument, :int ], :int
|
303
308
|
attach_function :testCallbackAsArgument, :testArgumentClosure, [ :cb_with_cb_argument, :int ], :int
|
@@ -306,6 +311,7 @@ describe "Callback" do
|
|
306
311
|
it 'should be able to use the callback argument' do
|
307
312
|
module LibTest
|
308
313
|
extend FFI::Library
|
314
|
+
ffi_lib TestLibrary::PATH
|
309
315
|
callback :cb_argument, [ :int ], :int
|
310
316
|
callback :cb_with_cb_argument, [ :cb_argument, :int ], :int
|
311
317
|
attach_function :testCallbackAsArgument, :testArgumentClosure, [ :cb_with_cb_argument, :cb_argument, :int ], :int
|
@@ -328,6 +334,7 @@ describe "Callback" do
|
|
328
334
|
it 'function returns callable object' do
|
329
335
|
module LibTest
|
330
336
|
extend FFI::Library
|
337
|
+
ffi_lib TestLibrary::PATH
|
331
338
|
callback :funcptr, [ :int ], :int
|
332
339
|
attach_function :testReturnsFunctionPointer, [ ], :funcptr
|
333
340
|
end
|
@@ -337,7 +344,7 @@ describe "Callback" do
|
|
337
344
|
end
|
338
345
|
|
339
346
|
end
|
340
|
-
describe "
|
347
|
+
describe "Callback with " do
|
341
348
|
#
|
342
349
|
# Test callbacks that take an argument, returning void
|
343
350
|
#
|
@@ -355,6 +362,8 @@ describe "primitive argument" do
|
|
355
362
|
|
356
363
|
callback :cbLrV, [ :long ], :void
|
357
364
|
callback :cbULrV, [ :ulong ], :void
|
365
|
+
callback :cbArV, [ :string ], :void
|
366
|
+
callback :cbPrV, [ :pointer], :void
|
358
367
|
|
359
368
|
callback :cbS64rV, [ :long_long ], :void
|
360
369
|
attach_function :testCallbackCrV, :testClosureBrV, [ :cbS8rV, :char ], :void
|
@@ -369,6 +378,8 @@ describe "primitive argument" do
|
|
369
378
|
attach_function :testCallbackULrV, :testClosureULrV, [ :cbULrV, :ulong ], :void
|
370
379
|
|
371
380
|
attach_function :testCallbackLLrV, :testClosureLLrV, [ :cbS64rV, :long_long ], :void
|
381
|
+
attach_function :testCallbackArV, :testClosurePrV, [ :cbArV, :string ], :void
|
382
|
+
attach_function :testCallbackPrV, :testClosurePrV, [ :cbPrV, :pointer], :void
|
372
383
|
end
|
373
384
|
it ":char (0) argument" do
|
374
385
|
v = 0xdeadbeef
|
@@ -556,5 +567,25 @@ describe "primitive argument" do
|
|
556
567
|
LibTest.testCallbackLLrV(-1) { |i| v = i }
|
557
568
|
v.should == -1
|
558
569
|
end
|
559
|
-
|
570
|
+
it ":string argument" do
|
571
|
+
v = nil
|
572
|
+
LibTest.testCallbackArV("Hello, World") { |i| v = i }
|
573
|
+
v.should == "Hello, World"
|
574
|
+
end
|
575
|
+
it ":string (nil) argument" do
|
576
|
+
v = "Hello, World"
|
577
|
+
LibTest.testCallbackArV(nil) { |i| v = i }
|
578
|
+
v.should be_nil
|
579
|
+
end
|
580
|
+
it ":pointer argument" do
|
581
|
+
v = nil
|
582
|
+
magic = FFI::Pointer.new(0xdeadbeef)
|
583
|
+
LibTest.testCallbackPrV(magic) { |i| v = i }
|
584
|
+
v.should == magic
|
585
|
+
end
|
586
|
+
it ":pointer (nil) argument" do
|
587
|
+
v = "Hello, World"
|
588
|
+
LibTest.testCallbackPrV(nil) { |i| v = i }
|
589
|
+
v.should == FFI::Pointer::NULL
|
590
|
+
end
|
560
591
|
end # unless true
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe FFI::Function do
|
4
|
+
before do
|
5
|
+
module LibTest
|
6
|
+
extend FFI::Library
|
7
|
+
ffi_lib TestLibrary::PATH
|
8
|
+
attach_function :testFunctionAdd, [:int, :int, :pointer], :int
|
9
|
+
end
|
10
|
+
@libtest = FFI::DynamicLibrary.open(TestLibrary::PATH,
|
11
|
+
FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL)
|
12
|
+
end
|
13
|
+
it 'is initialized with a signature and a block' do
|
14
|
+
FFI::Function.new(:int, []) { }
|
15
|
+
end
|
16
|
+
it 'raises an error when passing a wrong signature' do
|
17
|
+
lambda { FFI::Function.new([], :int).new { } }.should raise_error TypeError
|
18
|
+
end
|
19
|
+
it 'returns a native pointer' do
|
20
|
+
FFI::Function.new(:int, []) { }.kind_of? FFI::Pointer
|
21
|
+
end
|
22
|
+
it 'can be used as callback from C passing to it a block' do
|
23
|
+
function_add = FFI::Function.new(:int, [:int, :int]) { |a, b| a + b }
|
24
|
+
LibTest.testFunctionAdd(10, 10, function_add).should == 20
|
25
|
+
end
|
26
|
+
it 'can be used as callback from C passing to it a Proc object' do
|
27
|
+
function_add = FFI::Function.new(:int, [:int, :int], Proc.new { |a, b| a + b })
|
28
|
+
LibTest.testFunctionAdd(10, 10, function_add).should == 20
|
29
|
+
end
|
30
|
+
it 'can be used to wrap an existing function pointer' do
|
31
|
+
FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd')).call(10, 10).should == 20
|
32
|
+
end
|
33
|
+
it 'can be attached to a module' do
|
34
|
+
module Foo; end
|
35
|
+
fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd'))
|
36
|
+
fp.attach(Foo, 'add')
|
37
|
+
Foo.add(10, 10).should == 20
|
38
|
+
end
|
39
|
+
it 'can be used to extend an object' do
|
40
|
+
fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd'))
|
41
|
+
foo = Object.new
|
42
|
+
class << foo
|
43
|
+
def singleton_class
|
44
|
+
class << self; self; end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
fp.attach(foo.singleton_class, 'add')
|
48
|
+
foo.add(10, 10).should == 20
|
49
|
+
end
|
50
|
+
it 'can wrap a blocking function' do
|
51
|
+
unless RUBY_VERSION =~ /1.8/
|
52
|
+
fp = FFI::Function.new(:void, [ :int ], @libtest.find_function('testBlocking'), :blocking => true)
|
53
|
+
time = Time.now
|
54
|
+
threads = []
|
55
|
+
threads << Thread.new { fp.call(2) }
|
56
|
+
threads << Thread.new(time) { (Time.now - time).should < 1 }
|
57
|
+
threads.each { |t| t.join }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
it 'autorelease flag is set to true by default' do
|
61
|
+
fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd'))
|
62
|
+
fp.autorelease?.should be_true
|
63
|
+
end
|
64
|
+
it 'can explicity free itself' do
|
65
|
+
fp = FFI::Function.new(:int, []) { }
|
66
|
+
fp.free
|
67
|
+
lambda { fp.free }.should raise_error RuntimeError
|
68
|
+
end
|
69
|
+
it 'can\'t explicity free itself if not previously allocated' do
|
70
|
+
fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd'))
|
71
|
+
lambda { fp.free }.should raise_error RuntimeError
|
72
|
+
end
|
73
|
+
end
|
data/spec/ffi/library_spec.rb
CHANGED
@@ -1,57 +1,61 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
2
|
describe "Library" do
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
3
|
+
|
4
|
+
unless Config::CONFIG['target_os'] =~ /mingw/ || Config::CONFIG['target_os'] =~ /win/
|
5
|
+
it "attach_function with no library specified" do
|
6
|
+
lambda {
|
7
|
+
Module.new do |m|
|
8
|
+
m.extend FFI::Library
|
9
|
+
attach_function :getpid, [ ], :uint
|
10
|
+
end
|
11
|
+
}.should_not raise_error
|
12
|
+
end
|
13
|
+
it "attach_function :getpid from this process" do
|
14
|
+
lambda {
|
15
|
+
Module.new do |m|
|
16
|
+
m.extend FFI::Library
|
17
|
+
attach_function :getpid, [ ], :uint
|
18
|
+
end.getpid.should == Process.pid
|
19
|
+
}.should_not raise_error
|
20
|
+
end
|
21
|
+
it "attach_function :getpid from [ 'c', 'libc.so.6'] " do
|
22
|
+
lambda {
|
23
|
+
Module.new do |m|
|
24
|
+
m.extend FFI::Library
|
25
|
+
ffi_lib 'c', 'libc.so.6'
|
26
|
+
attach_function :getpid, [ ], :uint
|
27
|
+
end.getpid.should == Process.pid
|
28
|
+
}.should_not raise_error
|
29
|
+
end
|
30
|
+
it "attach_function :getpid from [ 'libc.so.6', 'c' ] " do
|
31
|
+
lambda {
|
32
|
+
Module.new do |m|
|
33
|
+
m.extend FFI::Library
|
34
|
+
ffi_lib 'libc.so.6', 'c'
|
35
|
+
attach_function :getpid, [ ], :uint
|
36
|
+
end.getpid.should == Process.pid
|
37
|
+
}.should_not raise_error
|
38
|
+
end
|
39
|
+
it "attach_function :getpid from [ 'libfubar.so.0xdeadbeef', nil, 'c' ] " do
|
40
|
+
lambda {
|
41
|
+
Module.new do |m|
|
42
|
+
m.extend FFI::Library
|
43
|
+
ffi_lib 'libfubar.so.0xdeadbeef', nil, 'c'
|
44
|
+
attach_function :getpid, [ ], :uint
|
45
|
+
end.getpid.should == Process.pid
|
46
|
+
}.should_not raise_error
|
47
|
+
end
|
48
|
+
it "attach_function :getpid from [ 'libfubar.so.0xdeadbeef' ] " do
|
49
|
+
lambda {
|
50
|
+
Module.new do |m|
|
51
|
+
m.extend FFI::Library
|
52
|
+
ffi_lib 'libfubar.so.0xdeadbeef'
|
53
|
+
attach_function :getpid, [ ], :uint
|
54
|
+
end.getpid.should == Process.pid
|
55
|
+
}.should raise_error(LoadError)
|
56
|
+
end
|
54
57
|
end
|
58
|
+
|
55
59
|
def gvar_lib(name, type)
|
56
60
|
Module.new do |m|
|
57
61
|
m.extend FFI::Library
|
@@ -141,4 +145,4 @@ describe "Library" do
|
|
141
145
|
lib.gvar = val
|
142
146
|
lib.get.should == val
|
143
147
|
end
|
144
|
-
end
|
148
|
+
end
|
data/spec/ffi/pointer_spec.rb
CHANGED
@@ -182,13 +182,13 @@ describe "AutoPointer#new" do
|
|
182
182
|
class AutoPointerSubclass < FFI::AutoPointer
|
183
183
|
def self.release(ptr); end
|
184
184
|
end
|
185
|
-
it "MemoryPointer argument raises
|
185
|
+
it "MemoryPointer argument raises TypeError" do
|
186
186
|
lambda { FFI::AutoPointer.new(FFI::MemoryPointer.new(:int))}.should raise_error(::TypeError)
|
187
187
|
end
|
188
|
-
it "AutoPointer argument raises
|
188
|
+
it "AutoPointer argument raises TypeError" do
|
189
189
|
lambda { AutoPointerSubclass.new(AutoPointerSubclass.new(LibTest.ptr_from_address(0))) }.should raise_error(::TypeError)
|
190
190
|
end
|
191
|
-
it "Buffer argument raises
|
191
|
+
it "Buffer argument raises TypeError" do
|
192
192
|
lambda { FFI::AutoPointer.new(FFI::Buffer.new(:int))}.should raise_error(::TypeError)
|
193
193
|
end
|
194
194
|
|
@@ -5,11 +5,13 @@ describe FFI::Struct, ' with inline callback functions' do
|
|
5
5
|
module CallbackMember
|
6
6
|
extend FFI::Library
|
7
7
|
ffi_lib TestLibrary::PATH
|
8
|
+
DUMMY_CB = callback :dummy_cb, [ :int ], :int
|
8
9
|
class TestStruct < FFI::Struct
|
9
10
|
layout \
|
10
11
|
:add, callback([ :int, :int ], :int),
|
11
|
-
:sub, callback([ :int, :int ], :int)
|
12
|
-
|
12
|
+
:sub, callback([ :int, :int ], :int),
|
13
|
+
:cb_with_cb_parameter, callback([ DUMMY_CB, :int ], :int)
|
14
|
+
end
|
13
15
|
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
14
16
|
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
15
17
|
end
|
@@ -22,7 +24,7 @@ describe FFI::Struct, ' with inline callback functions' do
|
|
22
24
|
layout \
|
23
25
|
:add, callback([ :int, :int ], :int),
|
24
26
|
:sub, callback([ :int, :int ], :int)
|
25
|
-
|
27
|
+
end
|
26
28
|
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
27
29
|
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
28
30
|
end
|
@@ -37,5 +39,26 @@ describe FFI::Struct, ' with inline callback functions' do
|
|
37
39
|
|
38
40
|
CallbackMember.struct_call_add_cb(ts, 1, 2).should == 3
|
39
41
|
end
|
42
|
+
|
43
|
+
it 'should return callable object from []' do
|
44
|
+
module CallbackMember
|
45
|
+
extend FFI::Library
|
46
|
+
ffi_lib TestLibrary::PATH
|
47
|
+
class TestStruct < FFI::Struct
|
48
|
+
layout \
|
49
|
+
:add, callback([ :int, :int ], :int),
|
50
|
+
:sub, callback([ :int, :int ], :int)
|
51
|
+
end
|
52
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
53
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
54
|
+
end
|
55
|
+
|
56
|
+
s = CallbackMember::TestStruct.new
|
57
|
+
add = Proc.new { |a,b| a+b}
|
58
|
+
s[:add] = add
|
59
|
+
fn = s[:add]
|
60
|
+
fn.respond_to?(:call).should be_true
|
61
|
+
fn.call(1, 2).should == 3
|
62
|
+
end
|
40
63
|
end
|
41
64
|
|
data/spec/ffi/struct_spec.rb
CHANGED
@@ -379,6 +379,59 @@ describe FFI::Struct, ' with a nested struct field' do
|
|
379
379
|
end
|
380
380
|
end
|
381
381
|
|
382
|
+
describe FFI::Struct, ' by value' do
|
383
|
+
module LibTest
|
384
|
+
extend FFI::Library
|
385
|
+
ffi_lib TestLibrary::PATH
|
386
|
+
|
387
|
+
class S8S32 < FFI::Struct
|
388
|
+
layout :s8, :char, :s32, :int
|
389
|
+
end
|
390
|
+
attach_function :struct_return_s8s32, [ ], S8S32.by_value
|
391
|
+
attach_function :struct_s8s32_set, [ :char, :int ], S8S32.by_value
|
392
|
+
attach_function :struct_s8s32_get_s8, [ S8S32.by_value ], :char
|
393
|
+
attach_function :struct_s8s32_get_s32, [ S8S32.by_value ], :int
|
394
|
+
attach_function :struct_s8s32_s32_ret_s32, [ S8S32.by_value, :int ], :int
|
395
|
+
attach_function :struct_s8s32_s64_ret_s64, [ S8S32.by_value, :long_long ], :long_long
|
396
|
+
end
|
397
|
+
|
398
|
+
it 'return using pre-set values' do
|
399
|
+
s = LibTest.struct_return_s8s32
|
400
|
+
s[:s8].should == 0x7f
|
401
|
+
s[:s32].should == 0x12345678
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'return using passed in values' do
|
405
|
+
s = LibTest.struct_s8s32_set(123, 456789)
|
406
|
+
s[:s8].should == 123
|
407
|
+
s[:s32].should == 456789
|
408
|
+
end
|
409
|
+
|
410
|
+
it 'parameter' do
|
411
|
+
s = LibTest::S8S32.new
|
412
|
+
s[:s8] = 0x12
|
413
|
+
s[:s32] = 0x34567890
|
414
|
+
LibTest.struct_s8s32_get_s8(s).should == 0x12
|
415
|
+
LibTest.struct_s8s32_get_s32(s).should == 0x34567890
|
416
|
+
end
|
417
|
+
|
418
|
+
it 'parameter with following s32' do
|
419
|
+
s = LibTest::S8S32.new
|
420
|
+
s[:s8] = 0x12
|
421
|
+
s[:s32] = 0x34567890
|
422
|
+
|
423
|
+
LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead).should == 0x1eefdead
|
424
|
+
end
|
425
|
+
|
426
|
+
it 'parameter with following s64' do
|
427
|
+
s = LibTest::S8S32.new
|
428
|
+
s[:s8] = 0x12
|
429
|
+
s[:s32] = 0x34567890
|
430
|
+
|
431
|
+
LibTest.struct_s8s32_s64_ret_s64(s, 0xdeadcafebabe).should == 0xdeadcafebabe
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
382
435
|
describe FFI::Struct, ' with an array field' do
|
383
436
|
module LibTest
|
384
437
|
extend FFI::Library
|
@@ -399,9 +452,9 @@ describe FFI::Struct, ' with an array field' do
|
|
399
452
|
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
400
453
|
@s[:a].to_a.should == [0, 1, 2, 3, 4]
|
401
454
|
end
|
402
|
-
it 'should cache array object for successive calls' do
|
403
|
-
@s[:a].object_id.should == @s[:a].object_id
|
404
|
-
end
|
455
|
+
# it 'should cache array object for successive calls' do
|
456
|
+
# @s[:a].object_id.should == @s[:a].object_id
|
457
|
+
# end
|
405
458
|
it 'should return the size of the array field in bytes' do
|
406
459
|
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
407
460
|
@s[:a].size.should == 20
|