ffi 0.3.5 → 0.4.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 +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
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
require 'java' if RUBY_PLATFORM =~ /java/
|
2
3
|
|
3
4
|
describe "Managed Struct" do
|
4
5
|
include FFI
|
@@ -33,7 +34,11 @@ describe "Managed Struct" do
|
|
33
34
|
loop = 5
|
34
35
|
while loop > 0 && @@count < count
|
35
36
|
loop -= 1
|
36
|
-
|
37
|
+
if RUBY_PLATFORM =~ /java/
|
38
|
+
java.lang.System.gc
|
39
|
+
else
|
40
|
+
GC.start
|
41
|
+
end
|
37
42
|
sleep 0.05 if @@count < count
|
38
43
|
end
|
39
44
|
end
|
data/spec/ffi/number_spec.rb
CHANGED
@@ -20,6 +20,36 @@ describe "Function with primitive integer arguments" do
|
|
20
20
|
attach_function :set_double, [ :double ], :void
|
21
21
|
attach_function :get_double, [ ], :double
|
22
22
|
end
|
23
|
+
it "int8.size" do
|
24
|
+
FFI::TYPE_INT8.size.should == 1
|
25
|
+
end
|
26
|
+
it "uint8.size" do
|
27
|
+
FFI::TYPE_UINT8.size.should == 1
|
28
|
+
end
|
29
|
+
it "int16.size" do
|
30
|
+
FFI::TYPE_INT16.size.should == 2
|
31
|
+
end
|
32
|
+
it "uint16.size" do
|
33
|
+
FFI::TYPE_UINT16.size.should == 2
|
34
|
+
end
|
35
|
+
it "int32.size" do
|
36
|
+
FFI::TYPE_INT32.size.should == 4
|
37
|
+
end
|
38
|
+
it "uint32.size" do
|
39
|
+
FFI::TYPE_UINT32.size.should == 4
|
40
|
+
end
|
41
|
+
it "int64.size" do
|
42
|
+
FFI::TYPE_INT64.size.should == 8
|
43
|
+
end
|
44
|
+
it "uint64.size" do
|
45
|
+
FFI::TYPE_UINT64.size.should == 8
|
46
|
+
end
|
47
|
+
it "float.size" do
|
48
|
+
FFI::TYPE_FLOAT32.size.should == 4
|
49
|
+
end
|
50
|
+
it "double.size" do
|
51
|
+
FFI::TYPE_FLOAT64.size.should == 8
|
52
|
+
end
|
23
53
|
[ 0, 127, -128, -1 ].each do |i|
|
24
54
|
it ":char call(:char (#{i}))" do
|
25
55
|
LibTest.ret_s8(i).should == i
|
data/spec/ffi/pointer_spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
2
|
require 'delegate'
|
3
|
+
require 'java' if RUBY_PLATFORM =~ /java/
|
4
|
+
|
3
5
|
module LibTest
|
4
6
|
attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
|
5
7
|
attach_function :ptr_from_address, [ FFI::Platform::ADDRESS_SIZE == 32 ? :uint : :ulong_long ], :pointer
|
@@ -25,7 +27,6 @@ describe "Pointer" do
|
|
25
27
|
end
|
26
28
|
class PointerDelegate < DelegateClass(FFI::Pointer)
|
27
29
|
def initialize(ptr)
|
28
|
-
super
|
29
30
|
@ptr = ptr
|
30
31
|
end
|
31
32
|
def to_ptr
|
@@ -84,7 +85,22 @@ describe "Pointer" do
|
|
84
85
|
array[j].address.should == address
|
85
86
|
end
|
86
87
|
end
|
88
|
+
|
89
|
+
end
|
87
90
|
|
91
|
+
describe 'NULL' do
|
92
|
+
it 'should be obtained using Pointer::NULL constant' do
|
93
|
+
null_ptr = FFI::Pointer::NULL
|
94
|
+
null_ptr.null?.should be_true
|
95
|
+
end
|
96
|
+
it 'should be obtained passing address 0 to constructor' do
|
97
|
+
FFI::Pointer.new(0).null?.should be_true
|
98
|
+
end
|
99
|
+
it 'should raise an error when attempting read/write operations on it' do
|
100
|
+
null_ptr = FFI::Pointer::NULL
|
101
|
+
lambda { null_ptr.read_int }.should raise_error(FFI::NullPointerError)
|
102
|
+
lambda { null_ptr.write_int(0xff1) }.should raise_error(FFI::NullPointerError)
|
103
|
+
end
|
88
104
|
end
|
89
105
|
|
90
106
|
end
|
@@ -106,7 +122,11 @@ describe "AutoPointer" do
|
|
106
122
|
loop = 5
|
107
123
|
while @@count < count && loop > 0
|
108
124
|
loop -= 1
|
109
|
-
|
125
|
+
if RUBY_PLATFORM =~ /java/
|
126
|
+
java.lang.System.gc
|
127
|
+
else
|
128
|
+
GC.start
|
129
|
+
end
|
110
130
|
sleep 0.05 unless @@count == count
|
111
131
|
end
|
112
132
|
@@count = 0
|
@@ -115,15 +135,17 @@ describe "AutoPointer" do
|
|
115
135
|
self.method(:release).to_proc
|
116
136
|
end
|
117
137
|
end
|
118
|
-
|
138
|
+
class AutoPointerSubclass < FFI::AutoPointer
|
139
|
+
def self.release(ptr); end
|
140
|
+
end
|
119
141
|
it "cleanup via default release method" do
|
120
|
-
|
142
|
+
AutoPointerSubclass.should_receive(:release).at_least(loop_count-wiggle_room).times
|
121
143
|
AutoPointerTestHelper.reset
|
122
144
|
loop_count.times do
|
123
145
|
# note that if we called
|
124
146
|
# AutoPointerTestHelper.method(:release).to_proc inline, we'd
|
125
147
|
# have a reference to the pointer and it would never get GC'd.
|
126
|
-
ap =
|
148
|
+
ap = AutoPointerSubclass.new(LibTest.ptr_from_address(magic))
|
127
149
|
end
|
128
150
|
AutoPointerTestHelper.gc_everything loop_count
|
129
151
|
end
|
@@ -157,14 +179,17 @@ describe "AutoPointer" do
|
|
157
179
|
end
|
158
180
|
end
|
159
181
|
describe "AutoPointer#new" do
|
182
|
+
class AutoPointerSubclass < FFI::AutoPointer
|
183
|
+
def self.release(ptr); end
|
184
|
+
end
|
160
185
|
it "MemoryPointer argument raises ArgumentError" do
|
161
|
-
lambda { FFI::AutoPointer.new(FFI::MemoryPointer.new(:int))}.should raise_error(
|
186
|
+
lambda { FFI::AutoPointer.new(FFI::MemoryPointer.new(:int))}.should raise_error(::TypeError)
|
162
187
|
end
|
163
188
|
it "AutoPointer argument raises ArgumentError" do
|
164
|
-
lambda {
|
189
|
+
lambda { AutoPointerSubclass.new(AutoPointerSubclass.new(LibTest.ptr_from_address(0))) }.should raise_error(::TypeError)
|
165
190
|
end
|
166
191
|
it "Buffer argument raises ArgumentError" do
|
167
|
-
lambda { FFI::AutoPointer.new(FFI::Buffer.new(:int))}.should raise_error(
|
192
|
+
lambda { FFI::AutoPointer.new(FFI::Buffer.new(:int))}.should raise_error(::TypeError)
|
168
193
|
end
|
169
194
|
|
170
195
|
end
|
@@ -18,12 +18,6 @@ describe "MemoryPointer" do
|
|
18
18
|
m.read_string.should == "FFI is Awesome"
|
19
19
|
end
|
20
20
|
|
21
|
-
it "reads back a string from an Array of ints" do
|
22
|
-
m = FFI::MemoryPointer.new(:int, 4)
|
23
|
-
m.write_array_of_int([541673030, 1092645737, 1869833591, 538994029])
|
24
|
-
m.read_string(16).should == "FFI is Awesome "
|
25
|
-
end
|
26
|
-
|
27
21
|
it "makes a pointer for a certain number of bytes" do
|
28
22
|
m = FFI::MemoryPointer.new(8)
|
29
23
|
m.write_array_of_int([1,2])
|
data/spec/ffi/spec_helper.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'rbconfig'
|
2
3
|
require 'spec'
|
3
4
|
|
4
|
-
|
5
|
+
if ENV["MRI_FFI"]
|
6
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "..", "lib"),
|
7
|
+
File.join(File.dirname(__FILE__), "..", "..", "build", "#{Config::CONFIG['host_cpu''arch']}", "ffi_c", RUBY_VERSION)
|
8
|
+
end
|
5
9
|
require "ffi"
|
6
10
|
|
7
11
|
module TestLibrary
|
data/spec/ffi/string_spec.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
2
|
describe "String tests" do
|
3
3
|
include FFI
|
4
|
-
module
|
4
|
+
module StrLibTest
|
5
5
|
extend FFI::Library
|
6
6
|
ffi_lib TestLibrary::PATH
|
7
7
|
attach_function :ptr_ret_pointer, [ :pointer, :int], :string
|
8
8
|
attach_function :string_equals, [ :string, :string ], :int
|
9
9
|
attach_function :string_dummy, [ :string ], :void
|
10
|
+
attach_function :string_null, [ ], :string
|
10
11
|
end
|
11
12
|
it "MemoryPointer#get_string returns a tainted string" do
|
12
13
|
mp = MemoryPointer.new 1024
|
@@ -19,13 +20,13 @@ describe "String tests" do
|
|
19
20
|
sp = MemoryPointer.new 1024
|
20
21
|
sp.put_string(0, "test")
|
21
22
|
mp.put_pointer(0, sp)
|
22
|
-
str =
|
23
|
+
str = StrLibTest.ptr_ret_pointer(mp, 0)
|
23
24
|
str.should == "test"
|
24
25
|
str.tainted?.should == true
|
25
26
|
end
|
26
27
|
it "Poison null byte raises error" do
|
27
28
|
s = "123\0abc"
|
28
|
-
lambda {
|
29
|
+
lambda { StrLibTest.string_equals(s, s) }.should raise_error
|
29
30
|
end
|
30
31
|
it "Tainted String parameter should throw a SecurityError" do
|
31
32
|
$SAFE = 1
|
@@ -37,6 +38,66 @@ describe "String tests" do
|
|
37
38
|
end
|
38
39
|
end if false
|
39
40
|
it "casts nil as NULL pointer" do
|
40
|
-
|
41
|
+
StrLibTest.string_dummy(nil)
|
42
|
+
end
|
43
|
+
it "return nil for NULL char*" do
|
44
|
+
StrLibTest.string_null.should == nil
|
45
|
+
end
|
46
|
+
it "reads an array of strings until encountering a NULL pointer" do
|
47
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
48
|
+
ptrary = MemoryPointer.new(:pointer, 6)
|
49
|
+
ary = strings.inject([]) do |a, str|
|
50
|
+
f = MemoryPointer.new(1024)
|
51
|
+
f.put_string(0, str)
|
52
|
+
a << f
|
53
|
+
end
|
54
|
+
ary.insert(3, nil)
|
55
|
+
ptrary.write_array_of_pointer(ary)
|
56
|
+
ptrary.get_array_of_string(0).should == ["foo", "bar", "baz"]
|
57
|
+
end
|
58
|
+
it "reads an array of strings of the size specified, substituting nil when a pointer is NULL" do
|
59
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
60
|
+
ptrary = MemoryPointer.new(:pointer, 6)
|
61
|
+
ary = strings.inject([]) do |a, str|
|
62
|
+
f = MemoryPointer.new(1024)
|
63
|
+
f.put_string(0, str)
|
64
|
+
a << f
|
65
|
+
end
|
66
|
+
ary.insert(2, nil)
|
67
|
+
ptrary.write_array_of_pointer(ary)
|
68
|
+
ptrary.get_array_of_string(0, 4).should == ["foo", "bar", nil, "baz"]
|
69
|
+
end
|
70
|
+
it "reads an array of strings, taking a memory offset parameter" do
|
71
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
72
|
+
ptrary = MemoryPointer.new(:pointer, 5)
|
73
|
+
ary = strings.inject([]) do |a, str|
|
74
|
+
f = MemoryPointer.new(1024)
|
75
|
+
f.put_string(0, str)
|
76
|
+
a << f
|
77
|
+
end
|
78
|
+
ptrary.write_array_of_pointer(ary)
|
79
|
+
ptrary.get_array_of_string(2 * FFI.type_size(:pointer), 3).should == ["baz", "testing", "ffi"]
|
80
|
+
end
|
81
|
+
it "raises an IndexError when trying to read an array of strings out of bounds" do
|
82
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
83
|
+
ptrary = MemoryPointer.new(:pointer, 5)
|
84
|
+
ary = strings.inject([]) do |a, str|
|
85
|
+
f = MemoryPointer.new(1024)
|
86
|
+
f.put_string(0, str)
|
87
|
+
a << f
|
88
|
+
end
|
89
|
+
ptrary.write_array_of_pointer(ary)
|
90
|
+
lambda { ptrary.get_array_of_string(0, 6) }.should raise_error
|
91
|
+
end
|
92
|
+
it "raises an IndexError when trying to read an array of strings using a negative offset" do
|
93
|
+
strings = ["foo", "bar", "baz", "testing", "ffi"]
|
94
|
+
ptrary = MemoryPointer.new(:pointer, 5)
|
95
|
+
ary = strings.inject([]) do |a, str|
|
96
|
+
f = MemoryPointer.new(1024)
|
97
|
+
f.put_string(0, str)
|
98
|
+
a << f
|
99
|
+
end
|
100
|
+
ptrary.write_array_of_pointer(ary)
|
101
|
+
lambda { ptrary.get_array_of_string(-1) }.should raise_error
|
41
102
|
end
|
42
103
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe FFI::Struct, ' with inline callback functions' do
|
4
|
+
it 'should be able to define inline callback field' do
|
5
|
+
module CallbackMember
|
6
|
+
extend FFI::Library
|
7
|
+
ffi_lib TestLibrary::PATH
|
8
|
+
class TestStruct < FFI::Struct
|
9
|
+
layout \
|
10
|
+
:add, callback([ :int, :int ], :int),
|
11
|
+
:sub, callback([ :int, :int ], :int)
|
12
|
+
end
|
13
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
14
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
15
|
+
end
|
16
|
+
end
|
17
|
+
it 'should take methods as callbacks' do
|
18
|
+
module CallbackMember
|
19
|
+
extend FFI::Library
|
20
|
+
ffi_lib TestLibrary::PATH
|
21
|
+
class TestStruct < FFI::Struct
|
22
|
+
layout \
|
23
|
+
:add, callback([ :int, :int ], :int),
|
24
|
+
:sub, callback([ :int, :int ], :int)
|
25
|
+
end
|
26
|
+
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
|
27
|
+
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
|
28
|
+
end
|
29
|
+
module StructCallbacks
|
30
|
+
def self.add a, b
|
31
|
+
a+b
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
ts = CallbackMember::TestStruct.new
|
36
|
+
ts[:add] = StructCallbacks.method(:add)
|
37
|
+
|
38
|
+
CallbackMember.struct_call_add_cb(ts, 1, 2).should == 3
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
|
+
|
3
|
+
describe FFI::Struct, ' with an initialize function' do
|
4
|
+
it "should call the initialize function" do
|
5
|
+
class StructWithInitialize < FFI::Struct
|
6
|
+
layout :string, :string
|
7
|
+
attr_accessor :magic
|
8
|
+
def initialize
|
9
|
+
super
|
10
|
+
self.magic = 42
|
11
|
+
end
|
12
|
+
end
|
13
|
+
StructWithInitialize.new.magic.should == 42
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe FFI::ManagedStruct, ' with an initialize function' do
|
18
|
+
it "should call the initialize function" do
|
19
|
+
class ManagedStructWithInitialize < FFI::ManagedStruct
|
20
|
+
layout :string, :string
|
21
|
+
attr_accessor :magic
|
22
|
+
def initialize
|
23
|
+
super MemoryPointer.new(:pointer).put_int(0, 0x1234).get_pointer(0)
|
24
|
+
self.magic = 42
|
25
|
+
end
|
26
|
+
def self.release;end
|
27
|
+
end
|
28
|
+
ManagedStructWithInitialize.new.magic.should == 42
|
29
|
+
end
|
30
|
+
end
|
data/spec/ffi/struct_spec.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
2
2
|
describe "Struct tests" do
|
3
|
-
include FFI
|
4
3
|
StructTypes = {
|
5
4
|
's8' => :char,
|
6
5
|
's16' => :short,
|
@@ -29,54 +28,54 @@ describe "Struct tests" do
|
|
29
28
|
end
|
30
29
|
it "Struct#[:pointer]" do
|
31
30
|
magic = 0x12345678
|
32
|
-
mp = MemoryPointer.new :long
|
31
|
+
mp = FFI::MemoryPointer.new :long
|
33
32
|
mp.put_long(0, magic)
|
34
|
-
smp = MemoryPointer.new :pointer
|
33
|
+
smp = FFI::MemoryPointer.new :pointer
|
35
34
|
smp.put_pointer(0, mp)
|
36
35
|
s = PointerMember.new smp
|
37
36
|
s[:pointer].should == mp
|
38
37
|
end
|
39
38
|
it "Struct#[:pointer].nil? for NULL value" do
|
40
39
|
magic = 0x12345678
|
41
|
-
mp = MemoryPointer.new :long
|
40
|
+
mp = FFI::MemoryPointer.new :long
|
42
41
|
mp.put_long(0, magic)
|
43
|
-
smp = MemoryPointer.new :pointer
|
42
|
+
smp = FFI::MemoryPointer.new :pointer
|
44
43
|
smp.put_pointer(0, nil)
|
45
44
|
s = PointerMember.new smp
|
46
45
|
s[:pointer].null?.should == true
|
47
46
|
end
|
48
47
|
it "Struct#[:pointer]=" do
|
49
48
|
magic = 0x12345678
|
50
|
-
mp = MemoryPointer.new :long
|
49
|
+
mp = FFI::MemoryPointer.new :long
|
51
50
|
mp.put_long(0, magic)
|
52
|
-
smp = MemoryPointer.new :pointer
|
51
|
+
smp = FFI::MemoryPointer.new :pointer
|
53
52
|
s = PointerMember.new smp
|
54
53
|
s[:pointer] = mp
|
55
54
|
smp.get_pointer(0).should == mp
|
56
55
|
end
|
57
56
|
it "Struct#[:pointer]=struct" do
|
58
57
|
magic = 0x12345678
|
59
|
-
smp = MemoryPointer.new :pointer
|
58
|
+
smp = FFI::MemoryPointer.new :pointer
|
60
59
|
s = PointerMember.new smp
|
61
60
|
lambda { s[:pointer] = s }.should_not raise_error
|
62
61
|
end
|
63
62
|
it "Struct#[:pointer]=nil" do
|
64
|
-
smp = MemoryPointer.new :pointer
|
63
|
+
smp = FFI::MemoryPointer.new :pointer
|
65
64
|
s = PointerMember.new smp
|
66
65
|
s[:pointer] = nil
|
67
66
|
smp.get_pointer(0).null?.should == true
|
68
67
|
end
|
69
68
|
it "Struct#[:string]" do
|
70
69
|
magic = "test"
|
71
|
-
mp = MemoryPointer.new 1024
|
70
|
+
mp = FFI::MemoryPointer.new 1024
|
72
71
|
mp.put_string(0, magic)
|
73
|
-
smp = MemoryPointer.new :pointer
|
72
|
+
smp = FFI::MemoryPointer.new :pointer
|
74
73
|
smp.put_pointer(0, mp)
|
75
74
|
s = StringMember.new smp
|
76
75
|
s[:string].should == magic
|
77
76
|
end
|
78
77
|
it "Struct#[:string].nil? for NULL value" do
|
79
|
-
smp = MemoryPointer.new :pointer
|
78
|
+
smp = FFI::MemoryPointer.new :pointer
|
80
79
|
smp.put_pointer(0, nil)
|
81
80
|
s = StringMember.new smp
|
82
81
|
s[:string].nil?.should == true
|
@@ -85,9 +84,9 @@ describe "Struct tests" do
|
|
85
84
|
class PairLayout < FFI::Struct
|
86
85
|
layout :a, :int, :b, :long_long
|
87
86
|
end
|
88
|
-
ll_off = (FFI::
|
87
|
+
ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8)
|
89
88
|
PairLayout.size.should == (ll_off + 8)
|
90
|
-
mp = MemoryPointer.new(PairLayout.size)
|
89
|
+
mp = FFI::MemoryPointer.new(PairLayout.size)
|
91
90
|
s = PairLayout.new mp
|
92
91
|
s[:a] = 0x12345678
|
93
92
|
mp.get_int(0).should == 0x12345678
|
@@ -98,8 +97,8 @@ describe "Struct tests" do
|
|
98
97
|
class PairLayout < FFI::Struct
|
99
98
|
layout :a, :int, 0, :b, :long_long, 4
|
100
99
|
end
|
101
|
-
PairLayout.size.should == (FFI::
|
102
|
-
mp = MemoryPointer.new(PairLayout.size)
|
100
|
+
PairLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
|
101
|
+
mp = FFI::MemoryPointer.new(PairLayout.size)
|
103
102
|
s = PairLayout.new mp
|
104
103
|
s[:a] = 0x12345678
|
105
104
|
mp.get_int(0).should == 0x12345678
|
@@ -110,8 +109,8 @@ describe "Struct tests" do
|
|
110
109
|
class MixedLayout < FFI::Struct
|
111
110
|
layout :a, :int, :b, :long_long, 4
|
112
111
|
end
|
113
|
-
MixedLayout.size.should == (FFI::
|
114
|
-
mp = MemoryPointer.new(MixedLayout.size)
|
112
|
+
MixedLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
|
113
|
+
mp = FFI::MemoryPointer.new(MixedLayout.size)
|
115
114
|
s = MixedLayout.new mp
|
116
115
|
s[:a] = 0x12345678
|
117
116
|
mp.get_int(0).should == 0x12345678
|
@@ -124,9 +123,9 @@ describe "Struct tests" do
|
|
124
123
|
class HashLayout < FFI::Struct
|
125
124
|
layout :a => :int, :b => :long_long
|
126
125
|
end
|
127
|
-
ll_off = (FFI::
|
126
|
+
ll_off = (FFI::TYPE_UINT64.alignment == 4? 4 : 8)
|
128
127
|
HashLayout.size.should == (ll_off + 8)
|
129
|
-
mp = MemoryPointer.new(HashLayout.size)
|
128
|
+
mp = FFI::MemoryPointer.new(HashLayout.size)
|
130
129
|
s = HashLayout.new mp
|
131
130
|
s[:a] = 0x12345678
|
132
131
|
mp.get_int(0).should == 0x12345678
|