alinta-ffi 1.9.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +49 -0
  3. data/LICENSE +24 -0
  4. data/README.md +112 -0
  5. data/Rakefile +243 -0
  6. data/ext/ffi_c/AbstractMemory.c +1109 -0
  7. data/ext/ffi_c/AbstractMemory.h +175 -0
  8. data/ext/ffi_c/ArrayType.c +162 -0
  9. data/ext/ffi_c/ArrayType.h +59 -0
  10. data/ext/ffi_c/Buffer.c +365 -0
  11. data/ext/ffi_c/Call.c +517 -0
  12. data/ext/ffi_c/Call.h +110 -0
  13. data/ext/ffi_c/ClosurePool.c +283 -0
  14. data/ext/ffi_c/ClosurePool.h +57 -0
  15. data/ext/ffi_c/DataConverter.c +91 -0
  16. data/ext/ffi_c/DynamicLibrary.c +339 -0
  17. data/ext/ffi_c/DynamicLibrary.h +98 -0
  18. data/ext/ffi_c/Function.c +998 -0
  19. data/ext/ffi_c/Function.h +87 -0
  20. data/ext/ffi_c/FunctionInfo.c +271 -0
  21. data/ext/ffi_c/LastError.c +184 -0
  22. data/ext/ffi_c/LastError.h +47 -0
  23. data/ext/ffi_c/LongDouble.c +63 -0
  24. data/ext/ffi_c/LongDouble.h +51 -0
  25. data/ext/ffi_c/MappedType.c +168 -0
  26. data/ext/ffi_c/MappedType.h +59 -0
  27. data/ext/ffi_c/MemoryPointer.c +197 -0
  28. data/ext/ffi_c/MemoryPointer.h +53 -0
  29. data/ext/ffi_c/MethodHandle.c +358 -0
  30. data/ext/ffi_c/MethodHandle.h +55 -0
  31. data/ext/ffi_c/Platform.c +129 -0
  32. data/ext/ffi_c/Platform.h +45 -0
  33. data/ext/ffi_c/Pointer.c +508 -0
  34. data/ext/ffi_c/Pointer.h +63 -0
  35. data/ext/ffi_c/Struct.c +829 -0
  36. data/ext/ffi_c/Struct.h +106 -0
  37. data/ext/ffi_c/StructByReference.c +190 -0
  38. data/ext/ffi_c/StructByReference.h +50 -0
  39. data/ext/ffi_c/StructByValue.c +150 -0
  40. data/ext/ffi_c/StructByValue.h +55 -0
  41. data/ext/ffi_c/StructLayout.c +698 -0
  42. data/ext/ffi_c/Thread.c +352 -0
  43. data/ext/ffi_c/Thread.h +95 -0
  44. data/ext/ffi_c/Type.c +397 -0
  45. data/ext/ffi_c/Type.h +62 -0
  46. data/ext/ffi_c/Types.c +139 -0
  47. data/ext/ffi_c/Types.h +89 -0
  48. data/ext/ffi_c/Variadic.c +304 -0
  49. data/ext/ffi_c/compat.h +78 -0
  50. data/ext/ffi_c/extconf.rb +71 -0
  51. data/ext/ffi_c/ffi.c +98 -0
  52. data/ext/ffi_c/libffi.bsd.mk +40 -0
  53. data/ext/ffi_c/libffi.darwin.mk +105 -0
  54. data/ext/ffi_c/libffi.gnu.mk +32 -0
  55. data/ext/ffi_c/libffi.mk +18 -0
  56. data/ext/ffi_c/libffi.vc.mk +26 -0
  57. data/ext/ffi_c/libffi.vc64.mk +26 -0
  58. data/ext/ffi_c/rbffi.h +57 -0
  59. data/ext/ffi_c/rbffi_endian.h +59 -0
  60. data/ext/ffi_c/win32/stdbool.h +8 -0
  61. data/ext/ffi_c/win32/stdint.h +201 -0
  62. data/ffi.gemspec +23 -0
  63. data/gen/Rakefile +30 -0
  64. data/lib/ffi.rb +20 -0
  65. data/lib/ffi/autopointer.rb +203 -0
  66. data/lib/ffi/buffer.rb +4 -0
  67. data/lib/ffi/callback.rb +4 -0
  68. data/lib/ffi/enum.rb +296 -0
  69. data/lib/ffi/errno.rb +43 -0
  70. data/lib/ffi/ffi.rb +44 -0
  71. data/lib/ffi/io.rb +62 -0
  72. data/lib/ffi/library.rb +590 -0
  73. data/lib/ffi/managedstruct.rb +84 -0
  74. data/lib/ffi/memorypointer.rb +1 -0
  75. data/lib/ffi/platform.rb +164 -0
  76. data/lib/ffi/platform/aarch64-linux/types.conf +104 -0
  77. data/lib/ffi/platform/arm-linux/types.conf +104 -0
  78. data/lib/ffi/platform/i386-cygwin/types.conf +3 -0
  79. data/lib/ffi/platform/i386-darwin/types.conf +100 -0
  80. data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  81. data/lib/ffi/platform/i386-gnu/types.conf +107 -0
  82. data/lib/ffi/platform/i386-linux/types.conf +103 -0
  83. data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  84. data/lib/ffi/platform/i386-openbsd/types.conf +128 -0
  85. data/lib/ffi/platform/i386-solaris/types.conf +122 -0
  86. data/lib/ffi/platform/i386-windows/types.conf +105 -0
  87. data/lib/ffi/platform/ia64-linux/types.conf +104 -0
  88. data/lib/ffi/platform/mips-linux/types.conf +102 -0
  89. data/lib/ffi/platform/mips64el-linux/types.conf +104 -0
  90. data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  91. data/lib/ffi/platform/powerpc-aix/types.conf +180 -0
  92. data/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
  93. data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
  94. data/lib/ffi/platform/powerpc64-linux/types.conf +104 -0
  95. data/lib/ffi/platform/s390-linux/types.conf +102 -0
  96. data/lib/ffi/platform/s390x-linux/types.conf +102 -0
  97. data/lib/ffi/platform/sparc-linux/types.conf +102 -0
  98. data/lib/ffi/platform/sparc-solaris/types.conf +128 -0
  99. data/lib/ffi/platform/sparc64-linux/types.conf +102 -0
  100. data/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
  101. data/lib/ffi/platform/x86_64-cygwin/types.conf +3 -0
  102. data/lib/ffi/platform/x86_64-darwin/types.conf +126 -0
  103. data/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
  104. data/lib/ffi/platform/x86_64-linux/types.conf +102 -0
  105. data/lib/ffi/platform/x86_64-netbsd/types.conf +128 -0
  106. data/lib/ffi/platform/x86_64-openbsd/types.conf +134 -0
  107. data/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
  108. data/lib/ffi/platform/x86_64-windows/types.conf +120 -0
  109. data/lib/ffi/pointer.rb +161 -0
  110. data/lib/ffi/struct.rb +371 -0
  111. data/lib/ffi/struct_layout_builder.rb +227 -0
  112. data/lib/ffi/tools/const_generator.rb +229 -0
  113. data/lib/ffi/tools/generator.rb +60 -0
  114. data/lib/ffi/tools/generator_task.rb +36 -0
  115. data/lib/ffi/tools/struct_generator.rb +194 -0
  116. data/lib/ffi/tools/types_generator.rb +134 -0
  117. data/lib/ffi/types.rb +194 -0
  118. data/lib/ffi/union.rb +43 -0
  119. data/lib/ffi/variadic.rb +78 -0
  120. data/lib/ffi/version.rb +4 -0
  121. data/libtest/Benchmark.c +52 -0
  122. data/libtest/BoolTest.c +34 -0
  123. data/libtest/BufferTest.c +31 -0
  124. data/libtest/ClosureTest.c +205 -0
  125. data/libtest/EnumTest.c +51 -0
  126. data/libtest/FunctionTest.c +70 -0
  127. data/libtest/GNUmakefile +149 -0
  128. data/libtest/GlobalVariable.c +62 -0
  129. data/libtest/LastErrorTest.c +21 -0
  130. data/libtest/NumberTest.c +132 -0
  131. data/libtest/PointerTest.c +63 -0
  132. data/libtest/ReferenceTest.c +23 -0
  133. data/libtest/StringTest.c +34 -0
  134. data/libtest/StructTest.c +243 -0
  135. data/libtest/UnionTest.c +43 -0
  136. data/libtest/VariadicTest.c +99 -0
  137. data/spec/ffi/LICENSE.SPECS +22 -0
  138. data/spec/ffi/async_callback_spec.rb +35 -0
  139. data/spec/ffi/bitmask_spec.rb +575 -0
  140. data/spec/ffi/bool_spec.rb +32 -0
  141. data/spec/ffi/buffer_spec.rb +279 -0
  142. data/spec/ffi/callback_spec.rb +773 -0
  143. data/spec/ffi/custom_param_type.rb +37 -0
  144. data/spec/ffi/custom_type_spec.rb +74 -0
  145. data/spec/ffi/dup_spec.rb +52 -0
  146. data/spec/ffi/enum_spec.rb +423 -0
  147. data/spec/ffi/errno_spec.rb +20 -0
  148. data/spec/ffi/ffi_spec.rb +28 -0
  149. data/spec/ffi/fixtures/Benchmark.c +52 -0
  150. data/spec/ffi/fixtures/BitmaskTest.c +51 -0
  151. data/spec/ffi/fixtures/BoolTest.c +34 -0
  152. data/spec/ffi/fixtures/BufferTest.c +31 -0
  153. data/spec/ffi/fixtures/ClosureTest.c +205 -0
  154. data/spec/ffi/fixtures/EnumTest.c +51 -0
  155. data/spec/ffi/fixtures/FunctionTest.c +142 -0
  156. data/spec/ffi/fixtures/GNUmakefile +149 -0
  157. data/spec/ffi/fixtures/GlobalVariable.c +62 -0
  158. data/spec/ffi/fixtures/LastErrorTest.c +21 -0
  159. data/spec/ffi/fixtures/NumberTest.c +132 -0
  160. data/spec/ffi/fixtures/PipeHelper.h +21 -0
  161. data/spec/ffi/fixtures/PipeHelperPosix.c +41 -0
  162. data/spec/ffi/fixtures/PipeHelperWindows.c +72 -0
  163. data/spec/ffi/fixtures/PointerTest.c +63 -0
  164. data/spec/ffi/fixtures/ReferenceTest.c +23 -0
  165. data/spec/ffi/fixtures/StringTest.c +34 -0
  166. data/spec/ffi/fixtures/StructTest.c +243 -0
  167. data/spec/ffi/fixtures/UnionTest.c +43 -0
  168. data/spec/ffi/fixtures/VariadicTest.c +99 -0
  169. data/spec/ffi/fixtures/classes.rb +438 -0
  170. data/spec/ffi/function_spec.rb +97 -0
  171. data/spec/ffi/io_spec.rb +16 -0
  172. data/spec/ffi/library_spec.rb +286 -0
  173. data/spec/ffi/long_double.rb +30 -0
  174. data/spec/ffi/managed_struct_spec.rb +68 -0
  175. data/spec/ffi/memorypointer_spec.rb +78 -0
  176. data/spec/ffi/number_spec.rb +247 -0
  177. data/spec/ffi/platform_spec.rb +114 -0
  178. data/spec/ffi/pointer_spec.rb +285 -0
  179. data/spec/ffi/rbx/attach_function_spec.rb +34 -0
  180. data/spec/ffi/rbx/memory_pointer_spec.rb +198 -0
  181. data/spec/ffi/rbx/spec_helper.rb +6 -0
  182. data/spec/ffi/rbx/struct_spec.rb +18 -0
  183. data/spec/ffi/spec_helper.rb +93 -0
  184. data/spec/ffi/string_spec.rb +118 -0
  185. data/spec/ffi/strptr_spec.rb +50 -0
  186. data/spec/ffi/struct_by_ref_spec.rb +43 -0
  187. data/spec/ffi/struct_callback_spec.rb +69 -0
  188. data/spec/ffi/struct_initialize_spec.rb +35 -0
  189. data/spec/ffi/struct_packed_spec.rb +50 -0
  190. data/spec/ffi/struct_spec.rb +882 -0
  191. data/spec/ffi/typedef_spec.rb +91 -0
  192. data/spec/ffi/union_spec.rb +67 -0
  193. data/spec/ffi/variadic_spec.rb +132 -0
  194. data/spec/spec.opts +4 -0
  195. metadata +309 -0
@@ -0,0 +1,32 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+
8
+ describe "Function with primitive boolean arguments and return values" do
9
+ module LibTest
10
+ extend FFI::Library
11
+ ffi_lib TestLibrary::PATH
12
+ attach_function :bool_return_true, [ ], :bool
13
+ attach_function :bool_return_false, [ ], :bool
14
+ attach_function :bool_return_val, [ :bool ], :bool
15
+ attach_function :bool_reverse_val, [ :bool ], :bool
16
+ end
17
+
18
+ it "bools" do
19
+ expect(LibTest.bool_return_true).to be true
20
+ expect(LibTest.bool_return_false).to be false
21
+
22
+ expect(LibTest.bool_return_val(true)).to be true
23
+ expect(LibTest.bool_return_val(false)).to be false
24
+
25
+ expect(LibTest.bool_reverse_val(true)).to be false
26
+ expect(LibTest.bool_reverse_val(false)).to be true
27
+ end
28
+
29
+ it "raise error on invalid types" do
30
+ expect { LibTest.bool_return_val(nil) }.to raise_error(::TypeError)
31
+ end
32
+ end
@@ -0,0 +1,279 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+
8
+ describe "Buffer#total" do
9
+ [1,2,3].each do |i|
10
+ { :char => 1, :uchar => 1, :short => 2, :ushort => 2, :int => 4,
11
+ :uint => 4, :long => FFI::Type::LONG.size, :ulong => FFI::Type::ULONG.size,
12
+ :long_long => 8, :ulong_long => 8, :float => 4, :double => 8
13
+ }.each_pair do |t, s|
14
+
15
+ it "Buffer.alloc_in(#{t}, #{i}).total == #{i * s}" do
16
+ expect(FFI::Buffer.alloc_in(t, i).total).to eq(i * s)
17
+ end
18
+
19
+ it "Buffer.alloc_out(#{t}, #{i}).total == #{i * s}" do
20
+ expect(FFI::Buffer.alloc_out(t, i).total).to eq(i * s)
21
+ end
22
+
23
+ it "Buffer.alloc_inout(#{t}, #{i}).total == #{i * s}" do
24
+ expect(FFI::Buffer.alloc_inout(t, i).total).to eq(i * s)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "Buffer#put_char" do
31
+ bufsize = 4
32
+ (0..127).each do |i|
33
+ (0..bufsize-1).each do |offset|
34
+ it "put_char(#{offset}, #{i}).get_char(#{offset}) == #{i}" do
35
+ expect(FFI::Buffer.alloc_in(bufsize).put_char(offset, i).get_char(offset)).to eq(i)
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "Buffer#put_uchar" do
42
+ bufsize = 4
43
+ (0..255).each do |i|
44
+ (0..bufsize-1).each do |offset|
45
+ it "Buffer.put_uchar(#{offset}, #{i}).get_uchar(#{offset}) == #{i}" do
46
+ expect(FFI::Buffer.alloc_in(bufsize).put_uchar(offset, i).get_uchar(offset)).to eq(i)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "Buffer#put_short" do
53
+ bufsize = 4
54
+ [0, 1, 128, 32767].each do |i|
55
+ (0..bufsize-2).each do |offset|
56
+ it "put_short(#{offset}, #{i}).get_short(#{offset}) == #{i}" do
57
+ expect(FFI::Buffer.alloc_in(bufsize).put_short(offset, i).get_short(offset)).to eq(i)
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "Buffer#put_ushort" do
64
+ bufsize = 4
65
+ [ 0, 1, 128, 32767, 65535, 0xfee1, 0xdead, 0xbeef, 0xcafe ].each do |i|
66
+ (0..bufsize-2).each do |offset|
67
+ it "put_ushort(#{offset}, #{i}).get_ushort(#{offset}) == #{i}" do
68
+ expect(FFI::Buffer.alloc_in(bufsize).put_ushort(offset, i).get_ushort(offset)).to eq(i)
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "Buffer#put_int" do
75
+ bufsize = 8
76
+ [0, 1, 128, 32767, 0x7ffffff ].each do |i|
77
+ (0..bufsize-4).each do |offset|
78
+ it "put_int(#{offset}, #{i}).get_int(#{offset}) == #{i}" do
79
+ expect(FFI::Buffer.alloc_in(bufsize).put_int(offset, i).get_int(offset)).to eq(i)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ describe "Buffer#put_uint" do
86
+ bufsize = 8
87
+ [ 0, 1, 128, 32767, 65535, 0xfee1dead, 0xcafebabe, 0xffffffff ].each do |i|
88
+ (0..bufsize-4).each do |offset|
89
+ it "put_uint(#{offset}, #{i}).get_uint(#{offset}) == #{i}" do
90
+ expect(FFI::Buffer.alloc_in(bufsize).put_uint(offset, i).get_uint(offset)).to eq(i)
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "Buffer#put_long" do
97
+ bufsize = 16
98
+ [0, 1, 128, 32767, 0x7ffffff ].each do |i|
99
+ (0..bufsize-FFI::Type::LONG.size).each do |offset|
100
+ it "put_long(#{offset}, #{i}).get_long(#{offset}) == #{i}" do
101
+ expect(FFI::Buffer.alloc_in(bufsize).put_long(offset, i).get_long(offset)).to eq(i)
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ describe "Buffer#put_ulong" do
108
+ bufsize = 16
109
+ [ 0, 1, 128, 32767, 65535, 0xfee1dead, 0xcafebabe, 0xffffffff ].each do |i|
110
+ (0..bufsize-FFI::Type::LONG.size).each do |offset|
111
+ it "put_ulong(#{offset}, #{i}).get_ulong(#{offset}) == #{i}" do
112
+ expect(FFI::Buffer.alloc_in(bufsize).put_ulong(offset, i).get_ulong(offset)).to eq(i)
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ describe "Buffer#put_long_long" do
119
+ bufsize = 16
120
+ [0, 1, 128, 32767, 0x7ffffffffffffff ].each do |i|
121
+ (0..bufsize-8).each do |offset|
122
+ it "put_long_long(#{offset}, #{i}).get_long_long(#{offset}) == #{i}" do
123
+ expect(FFI::Buffer.alloc_in(bufsize).put_long_long(offset, i).get_long_long(offset)).to eq(i)
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "Buffer#put_ulong_long" do
130
+ bufsize = 16
131
+ [ 0, 1, 128, 32767, 65535, 0xdeadcafebabe, 0x7fffffffffffffff ].each do |i|
132
+ (0..bufsize-8).each do |offset|
133
+ it "put_ulong_long(#{offset}, #{i}).get_ulong_long(#{offset}) == #{i}" do
134
+ expect(FFI::Buffer.alloc_in(bufsize).put_ulong_long(offset, i).get_ulong_long(offset)).to eq(i)
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ describe "Reading/Writing binary strings" do
141
+ it "Buffer#put_bytes" do
142
+ str = "hello\0world"
143
+ buf = FFI::Buffer.new 1024
144
+ buf.put_bytes(0, str);
145
+ s2 = buf.get_bytes(0, 11);
146
+ expect(s2).to eq(str)
147
+ end
148
+
149
+ it "Buffer#put_bytes with index and length" do
150
+ str = "hello\0world"
151
+ buf = FFI::Buffer.new 1024
152
+ buf.put_bytes(0, str, 5, 6);
153
+ s2 = buf.get_bytes(0, 6);
154
+ expect(s2).to eq(str[5..-1])
155
+ end
156
+
157
+ it "Buffer#put_bytes with only index" do
158
+ str = "hello\0world"
159
+ buf = FFI::Buffer.new 1024
160
+ buf.put_bytes(0, str, 5);
161
+ s2 = buf.get_bytes(0, 6);
162
+ expect(s2).to eq(str[5..-1])
163
+ end
164
+
165
+ it "Buffer#put_bytes with index > str.length" do
166
+ str = "hello\0world"
167
+ buf = FFI::Buffer.new 1024
168
+ expect { buf.put_bytes(0, str, 12); }.to raise_error
169
+ end
170
+
171
+ it "Buffer#put_bytes with length > str.length" do
172
+ str = "hello\0world"
173
+ buf = FFI::Buffer.new 1024
174
+ expect { buf.put_bytes(0, str, 0, 12); }.to raise_error
175
+ end
176
+
177
+ it "Buffer#put_bytes with negative index" do
178
+ str = "hello\0world"
179
+ buf = FFI::Buffer.new 1024
180
+ expect { buf.put_bytes(0, str, -1, 12); }.to raise_error
181
+ end
182
+
183
+ it "Buffer#write_bytes" do
184
+ str = "hello\0world"
185
+ buf = FFI::Buffer.new 1024
186
+ buf.write_bytes(str)
187
+ s2 = buf.get_bytes(0, 11)
188
+ expect(s2).to eq(str)
189
+ end
190
+
191
+ it "Buffer#write_bytes with index and length" do
192
+ str = "hello\0world"
193
+ buf = FFI::Buffer.new 1024
194
+ buf.write_bytes(str, 5, 6)
195
+ s2 = buf.get_bytes(0, 6)
196
+ expect(s2).to eq(str[5..-1])
197
+ end
198
+
199
+ it "Buffer#write_bytes with only index" do
200
+ str = "hello\0world"
201
+ buf = FFI::Buffer.new 1024
202
+ buf.write_bytes(str, 5)
203
+ s2 = buf.get_bytes(0, 6)
204
+ expect(s2).to eq(str[5..-1])
205
+ end
206
+
207
+ it "Buffer#write_bytes with index > str.length" do
208
+ str = "hello\0world"
209
+ buf = FFI::Buffer.new 1024
210
+ expect { buf.write_bytes(str, 12) }.to raise_error
211
+ end
212
+
213
+ it "Buffer#put_bytes with length > str.length" do
214
+ str = "hello\0world"
215
+ buf = FFI::Buffer.new 1024
216
+ expect { buf.put_bytes(0, str, 0, 12) }.to raise_error
217
+ end
218
+
219
+ it "Buffer#write_bytes with negative index" do
220
+ str = "hello\0world"
221
+ buf = FFI::Buffer.new 1024
222
+ expect { buf.write_bytes(str, -1, 12) }.to raise_error
223
+ end
224
+ end
225
+
226
+ describe "Reading/Writing ascii strings" do
227
+ it "Buffer#put_string with string containing zero byte" do
228
+ str = "hello\0world"
229
+ buf = FFI::Buffer.new 1024
230
+ buf.put_string(0, str);
231
+ s2 = buf.get_bytes(0, 11);
232
+ expect(s2).to eq(str)
233
+ end
234
+
235
+ it "Buffer#get_string with string containing zero byte" do
236
+ str = "hello\0world"
237
+ buf = FFI::Buffer.new 1024
238
+ buf.put_bytes(0, str);
239
+ s2 = buf.get_string(0, 11);
240
+ expect(s2).to eq("hello")
241
+ end
242
+
243
+ it "Buffer#put_string without length should NUL terminate" do
244
+ str = "hello"
245
+ buf = FFI::Buffer.new 1024
246
+ buf.put_string(0, str);
247
+ s2 = buf.get_bytes(0, 6);
248
+ expect(s2).to eq("hello\0")
249
+ end
250
+ end
251
+
252
+ describe "Buffer#put_pointer" do
253
+ it "put_pointer(0, p).get_pointer(0) == p" do
254
+ p = FFI::MemoryPointer.new :ulong_long
255
+ p.put_uint(0, 0xdeadbeef)
256
+ buf = FFI::Buffer.alloc_inout 8
257
+ p2 = buf.put_pointer(0, p).get_pointer(0)
258
+ expect(p2).not_to be_nil
259
+ expect(p2).to eq(p)
260
+ expect(p2.get_uint(0)).to eq(0xdeadbeef)
261
+ end
262
+ end
263
+
264
+ describe "Buffer#size" do
265
+ it "should return size" do
266
+ buf = FFI::Buffer.new 14
267
+ expect(buf.size).to eq(14)
268
+ end
269
+ end
270
+
271
+ describe "Buffer#initialize" do
272
+ it "with block should execute block" do
273
+ block_executed = false
274
+ FFI::Buffer.new(:pointer) do |ptr|
275
+ block_executed = true
276
+ end
277
+ expect(block_executed).to be true
278
+ end
279
+ end
@@ -0,0 +1,773 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+
8
+ describe "Callback" do
9
+ # module LibC
10
+ # extend FFI::Library
11
+ # callback :qsort_cmp, [ :pointer, :pointer ], :int
12
+ # attach_function :qsort, [ :pointer, :int, :int, :qsort_cmp ], :int
13
+ # end
14
+ # it "arguments get passed correctly" do
15
+ # p = MemoryPointer.new(:int, 2)
16
+ # p.put_array_of_int32(0, [ 1 , 2 ])
17
+ # args = []
18
+ # cmp = proc do |p1, p2| args.push(p1.get_int(0)); args.push(p2.get_int(0)); 0; end
19
+ # # this is a bit dodgey, as it relies on qsort passing the args in order
20
+ # LibC.qsort(p, 2, 4, cmp)
21
+ # args.should == [ 1, 2 ]
22
+ # end
23
+ #
24
+ # it "Block can be substituted for Callback as last argument" do
25
+ # p = MemoryPointer.new(:int, 2)
26
+ # p.put_array_of_int32(0, [ 1 , 2 ])
27
+ # args = []
28
+ # # this is a bit dodgey, as it relies on qsort passing the args in order
29
+ # LibC.qsort(p, 2, 4) do |p1, p2|
30
+ # args.push(p1.get_int(0))
31
+ # args.push(p2.get_int(0))
32
+ # 0
33
+ # end
34
+ # args.should == [ 1, 2 ]
35
+ # end
36
+ module LibTest
37
+ extend FFI::Library
38
+ ffi_lib TestLibrary::PATH
39
+ class S8F32S32 < FFI::Struct
40
+ layout :s8, :char, :f32, :float, :s32, :int
41
+ end
42
+
43
+ callback :cbVrS8, [ ], :char
44
+ callback :cbVrU8, [ ], :uchar
45
+ callback :cbVrS16, [ ], :short
46
+ callback :cbVrU16, [ ], :ushort
47
+ callback :cbVrS32, [ ], :int
48
+ callback :cbVrU32, [ ], :uint
49
+ callback :cbVrL, [ ], :long
50
+ callback :cbVrUL, [ ], :ulong
51
+ callback :cbVrS64, [ ], :long_long
52
+ callback :cbVrU64, [ ], :ulong_long
53
+ callback :cbVrP, [], :pointer
54
+ callback :cbVrZ, [], :bool
55
+ callback :cbCrV, [ :char ], :void
56
+ callback :cbSrV, [ :short ], :void
57
+ callback :cbIrV, [ :int ], :void
58
+ callback :cbLrV, [ :long ], :void
59
+ callback :cbULrV, [ :ulong ], :void
60
+ callback :cbLrV, [ :long_long ], :void
61
+ callback :cbVrT, [ ], S8F32S32.by_value
62
+ callback :cbTrV, [ S8F32S32.by_value ], :void
63
+ callback :cbYrV, [ S8F32S32.ptr ], :void
64
+ callback :cbVrY, [ ], S8F32S32.ptr
65
+
66
+ attach_function :testCallbackVrS8, :testClosureVrB, [ :cbVrS8 ], :char
67
+ attach_function :testCallbackVrU8, :testClosureVrB, [ :cbVrU8 ], :uchar
68
+ attach_function :testCallbackVrS16, :testClosureVrS, [ :cbVrS16 ], :short
69
+ attach_function :testCallbackVrU16, :testClosureVrS, [ :cbVrU16 ], :ushort
70
+ attach_function :testCallbackVrS32, :testClosureVrI, [ :cbVrS32 ], :int
71
+ attach_function :testCallbackVrU32, :testClosureVrI, [ :cbVrU32 ], :uint
72
+ attach_function :testCallbackVrL, :testClosureVrL, [ :cbVrL ], :long
73
+ attach_function :testCallbackVrZ, :testClosureVrZ, [ :cbVrZ ], :bool
74
+ attach_function :testCallbackVrUL, :testClosureVrL, [ :cbVrUL ], :ulong
75
+ attach_function :testCallbackVrS64, :testClosureVrLL, [ :cbVrS64 ], :long_long
76
+ attach_function :testCallbackVrU64, :testClosureVrLL, [ :cbVrU64 ], :ulong_long
77
+ attach_function :testCallbackVrP, :testClosureVrP, [ :cbVrP ], :pointer
78
+ attach_function :testCallbackVrY, :testClosureVrP, [ :cbVrY ], S8F32S32.ptr
79
+ attach_function :testCallbackVrT, :testClosureVrT, [ :cbVrT ], S8F32S32.by_value
80
+ attach_function :testCallbackTrV, :testClosureTrV, [ :cbTrV, S8F32S32.ptr ], :void
81
+ attach_variable :cbVrS8, :gvar_pointer, :cbVrS8
82
+ attach_variable :pVrS8, :gvar_pointer, :pointer
83
+ attach_function :testGVarCallbackVrS8, :testClosureVrB, [ :pointer ], :char
84
+ attach_function :testOptionalCallbackCrV, :testOptionalClosureBrV, [ :cbCrV, :char ], :void
85
+
86
+ end
87
+
88
+ it "returning :char (0)" do
89
+ expect(LibTest.testCallbackVrS8 { 0 }).to eq(0)
90
+ end
91
+
92
+ it "returning :char (127)" do
93
+ expect(LibTest.testCallbackVrS8 { 127 }).to eq(127)
94
+ end
95
+
96
+ it "returning :char (-128)" do
97
+ expect(LibTest.testCallbackVrS8 { -128 }).to eq(-128)
98
+ end
99
+ # test wrap around
100
+ it "returning :char (128)" do
101
+ expect(LibTest.testCallbackVrS8 { 128 }).to eq(-128)
102
+ end
103
+
104
+ it "returning :char (255)" do
105
+ expect(LibTest.testCallbackVrS8 { 0xff }).to eq(-1)
106
+ end
107
+
108
+ it "returning :uchar (0)" do
109
+ expect(LibTest.testCallbackVrU8 { 0 }).to eq(0)
110
+ end
111
+
112
+ it "returning :uchar (0xff)" do
113
+ expect(LibTest.testCallbackVrU8 { 0xff }).to eq(0xff)
114
+ end
115
+
116
+ it "returning :uchar (-1)" do
117
+ expect(LibTest.testCallbackVrU8 { -1 }).to eq(0xff)
118
+ end
119
+
120
+ it "returning :uchar (128)" do
121
+ expect(LibTest.testCallbackVrU8 { 128 }).to eq(128)
122
+ end
123
+
124
+ it "returning :uchar (-128)" do
125
+ expect(LibTest.testCallbackVrU8 { -128 }).to eq(128)
126
+ end
127
+
128
+ it "returning :short (0)" do
129
+ expect(LibTest.testCallbackVrS16 { 0 }).to eq(0)
130
+ end
131
+
132
+ it "returning :short (0x7fff)" do
133
+ expect(LibTest.testCallbackVrS16 { 0x7fff }).to eq(0x7fff)
134
+ end
135
+ # test wrap around
136
+ it "returning :short (0x8000)" do
137
+ expect(LibTest.testCallbackVrS16 { 0x8000 }).to eq(-0x8000)
138
+ end
139
+
140
+ it "returning :short (0xffff)" do
141
+ expect(LibTest.testCallbackVrS16 { 0xffff }).to eq(-1)
142
+ end
143
+
144
+ it "returning :ushort (0)" do
145
+ expect(LibTest.testCallbackVrU16 { 0 }).to eq(0)
146
+ end
147
+
148
+ it "returning :ushort (0x7fff)" do
149
+ expect(LibTest.testCallbackVrU16 { 0x7fff }).to eq(0x7fff)
150
+ end
151
+
152
+ it "returning :ushort (0x8000)" do
153
+ expect(LibTest.testCallbackVrU16 { 0x8000 }).to eq(0x8000)
154
+ end
155
+
156
+ it "returning :ushort (0xffff)" do
157
+ expect(LibTest.testCallbackVrU16 { 0xffff }).to eq(0xffff)
158
+ end
159
+
160
+ it "returning :ushort (-1)" do
161
+ expect(LibTest.testCallbackVrU16 { -1 }).to eq(0xffff)
162
+ end
163
+
164
+ it "returning :int (0)" do
165
+ expect(LibTest.testCallbackVrS32 { 0 }).to eq(0)
166
+ end
167
+
168
+ it "returning :int (0x7fffffff)" do
169
+ expect(LibTest.testCallbackVrS32 { 0x7fffffff }).to eq(0x7fffffff)
170
+ end
171
+ # test wrap around
172
+ it "returning :int (-0x80000000)" do
173
+ expect(LibTest.testCallbackVrS32 { -0x80000000 }).to eq(-0x80000000)
174
+ end
175
+
176
+ it "returning :int (-1)" do
177
+ expect(LibTest.testCallbackVrS32 { -1 }).to eq(-1)
178
+ end
179
+
180
+ it "returning :uint (0)" do
181
+ expect(LibTest.testCallbackVrU32 { 0 }).to eq(0)
182
+ end
183
+
184
+ it "returning :uint (0x7fffffff)" do
185
+ expect(LibTest.testCallbackVrU32 { 0x7fffffff }).to eq(0x7fffffff)
186
+ end
187
+ # test wrap around
188
+ it "returning :uint (0x80000000)" do
189
+ expect(LibTest.testCallbackVrU32 { 0x80000000 }).to eq(0x80000000)
190
+ end
191
+
192
+ it "returning :uint (0xffffffff)" do
193
+ expect(LibTest.testCallbackVrU32 { 0xffffffff }).to eq(0xffffffff)
194
+ end
195
+
196
+ it "returning :uint (-1)" do
197
+ expect(LibTest.testCallbackVrU32 { -1 }).to eq(0xffffffff)
198
+ end
199
+
200
+ it "returning :long (0)" do
201
+ expect(LibTest.testCallbackVrL { 0 }).to eq(0)
202
+ end
203
+
204
+ it "returning :long (0x7fffffff)" do
205
+ expect(LibTest.testCallbackVrL { 0x7fffffff }).to eq(0x7fffffff)
206
+ end
207
+ # test wrap around
208
+ it "returning :long (-0x80000000)" do
209
+ expect(LibTest.testCallbackVrL { -0x80000000 }).to eq(-0x80000000)
210
+ end
211
+
212
+ it "returning :long (-1)" do
213
+ expect(LibTest.testCallbackVrL { -1 }).to eq(-1)
214
+ end
215
+
216
+ it "returning :ulong (0)" do
217
+ expect(LibTest.testCallbackVrUL { 0 }).to eq(0)
218
+ end
219
+
220
+ it "returning :ulong (0x7fffffff)" do
221
+ expect(LibTest.testCallbackVrUL { 0x7fffffff }).to eq(0x7fffffff)
222
+ end
223
+ # test wrap around
224
+ it "returning :ulong (0x80000000)" do
225
+ expect(LibTest.testCallbackVrUL { 0x80000000 }).to eq(0x80000000)
226
+ end
227
+
228
+ it "returning :ulong (0xffffffff)" do
229
+ expect(LibTest.testCallbackVrUL { 0xffffffff }).to eq(0xffffffff)
230
+ end
231
+
232
+ it "Callback returning :ulong (-1)" do
233
+ if FFI::Platform::LONG_SIZE == 32
234
+ expect(LibTest.testCallbackVrUL { -1 }).to eq(0xffffffff)
235
+ else
236
+ expect(LibTest.testCallbackVrUL { -1 }).to eq(0xffffffffffffffff)
237
+ end
238
+ end
239
+
240
+ it "returning :long_long (0)" do
241
+ expect(LibTest.testCallbackVrS64 { 0 }).to eq(0)
242
+ end
243
+
244
+ it "returning :long_long (0x7fffffffffffffff)" do
245
+ expect(LibTest.testCallbackVrS64 { 0x7fffffffffffffff }).to eq(0x7fffffffffffffff)
246
+ end
247
+ # test wrap around
248
+ it "returning :long_long (-0x8000000000000000)" do
249
+ expect(LibTest.testCallbackVrS64 { -0x8000000000000000 }).to eq(-0x8000000000000000)
250
+ end
251
+
252
+ it "returning :long_long (-1)" do
253
+ expect(LibTest.testCallbackVrS64 { -1 }).to eq(-1)
254
+ end
255
+
256
+ it "returning bool" do
257
+ expect(LibTest.testCallbackVrZ { true }).to be true
258
+ end
259
+
260
+ it "returning :pointer (nil)" do
261
+ expect(LibTest.testCallbackVrP { nil }).to be_null
262
+ end
263
+
264
+ it "returning :pointer (MemoryPointer)" do
265
+ p = FFI::MemoryPointer.new :long
266
+ expect(LibTest.testCallbackVrP { p }).to eq(p)
267
+ end
268
+
269
+ it "returning struct by value" do
270
+ s = LibTest::S8F32S32.new
271
+ s[:s8] = 0x12
272
+ s[:s32] = 0x1eefbeef
273
+ s[:f32] = 1.234567
274
+ ret = LibTest.testCallbackVrT { s }
275
+ expect(ret[:s8]).to eq(s[:s8])
276
+ expect(ret[:f32]).to eq(s[:f32])
277
+ expect(ret[:s32]).to eq(s[:s32])
278
+
279
+ end
280
+
281
+ it "struct by value parameter" do
282
+ s = LibTest::S8F32S32.new
283
+ s[:s8] = 0x12
284
+ s[:s32] = 0x1eefbeef
285
+ s[:f32] = 1.234567
286
+ s2 = LibTest::S8F32S32.new
287
+
288
+ LibTest.testCallbackTrV(s) do |struct|
289
+ s2[:s8] = struct[:s8]
290
+ s2[:f32] = struct[:f32]
291
+ s2[:s32] = struct[:s32]
292
+ end
293
+
294
+ expect(s2[:s8]).to eql 0x12
295
+ expect(s2[:s32]).to eql 0x1eefbeef
296
+ expect(s2[:f32]).to be_within(0.0000001).of 1.234567
297
+ end
298
+
299
+
300
+ it "global variable" do
301
+ proc = Proc.new { 0x1e }
302
+ LibTest.cbVrS8 = proc
303
+ expect(LibTest.testGVarCallbackVrS8(LibTest.pVrS8)).to eq(0x1e)
304
+ end
305
+
306
+ describe "When the callback is considered optional by the underlying library" do
307
+ it "should handle receiving 'nil' in place of the closure" do
308
+ expect(LibTest.testOptionalCallbackCrV(nil, 13)).to be_nil
309
+ end
310
+ end
311
+
312
+ describe 'when inlined' do
313
+ it 'could be anonymous' do
314
+ module LibTest
315
+ extend FFI::Library
316
+ ffi_lib TestLibrary::PATH
317
+ attach_function :testAnonymousCallbackVrS8, :testClosureVrB, [ callback([ ], :char) ], :char
318
+ end
319
+ expect(LibTest.testAnonymousCallbackVrS8 { 0 }).to eq(0)
320
+ end
321
+ end
322
+
323
+ describe "as return value" do
324
+
325
+ it "should not blow up when a callback is defined that returns a callback" do
326
+ expect(module LibTest
327
+ extend FFI::Library
328
+ ffi_lib TestLibrary::PATH
329
+ callback :cb_return_type_1, [ :short ], :short
330
+ callback :cb_lookup_1, [ :short ], :cb_return_type_1
331
+ attach_function :testReturnsCallback_1, :testReturnsClosure, [ :cb_lookup_1, :short ], :cb_return_type_1
332
+ end).to be_an_instance_of FFI::Function
333
+ end
334
+
335
+ it "should return a callback" do
336
+ module LibTest
337
+ extend FFI::Library
338
+ ffi_lib TestLibrary::PATH
339
+ callback :cb_return_type, [ :int ], :int
340
+ callback :cb_lookup, [ ], :cb_return_type
341
+ attach_function :testReturnsCallback, :testReturnsClosure, [ :cb_lookup, :int ], :int
342
+ end
343
+
344
+ lookup_proc_called = false
345
+ return_proc_called = false
346
+
347
+ return_proc = Proc.new do |a|
348
+ return_proc_called = true
349
+ a * 2
350
+ end
351
+ lookup_proc = Proc.new do
352
+ lookup_proc_called = true
353
+ return_proc
354
+ end
355
+
356
+ val = LibTest.testReturnsCallback(lookup_proc, 0x1234)
357
+ expect(val).to eq(0x1234 * 2)
358
+ expect(lookup_proc_called).to be true
359
+ expect(return_proc_called).to be true
360
+ end
361
+
362
+ it "should return a method callback" do
363
+ module LibTest
364
+ extend FFI::Library
365
+ ffi_lib TestLibrary::PATH
366
+ callback :cb_return_type, [ :int ], :int
367
+ callback :cb_lookup, [ ], :cb_return_type
368
+ attach_function :testReturnsCallback_2, :testReturnsClosure, [ :cb_lookup, :int ], :int
369
+ end
370
+ module MethodCallback
371
+ def self.lookup
372
+ method(:perform)
373
+ end
374
+ def self.perform num
375
+ num * 2
376
+ end
377
+ end
378
+
379
+ expect(LibTest.testReturnsCallback_2(MethodCallback.method(:lookup), 0x1234)).to eq(0x2468)
380
+ end
381
+
382
+ it 'should not blow up when a callback takes a callback as argument' do
383
+ expect(module LibTest
384
+ extend FFI::Library
385
+ ffi_lib TestLibrary::PATH
386
+ callback :cb_argument, [ :int ], :int
387
+ callback :cb_with_cb_argument, [ :cb_argument, :int ], :int
388
+ attach_function :testCallbackAsArgument_2, :testArgumentClosure, [ :cb_with_cb_argument, :int ], :int
389
+ end).to be_an_instance_of FFI::Function
390
+ end
391
+ it 'should be able to use the callback argument' do
392
+ module LibTest
393
+ extend FFI::Library
394
+ ffi_lib TestLibrary::PATH
395
+ callback :cb_argument, [ :int ], :int
396
+ callback :cb_with_cb_argument, [ :cb_argument, :int ], :int
397
+ attach_function :testCallbackAsArgument, :testArgumentClosure, [ :cb_with_cb_argument, :cb_argument, :int ], :int
398
+ end
399
+ callback_arg_called = false
400
+ callback_with_callback_arg_called = false
401
+ callback_arg = Proc.new do |val|
402
+ callback_arg_called = true
403
+ val * 2
404
+ end
405
+ callback_with_callback_arg = Proc.new do |cb, val|
406
+ callback_with_callback_arg_called = true
407
+ cb.call(val)
408
+ end
409
+ val = LibTest.testCallbackAsArgument(callback_with_callback_arg, callback_arg, 0xff1)
410
+ expect(val).to eq(0xff1 * 2)
411
+ expect(callback_arg_called).to be true
412
+ expect(callback_with_callback_arg_called).to be true
413
+ end
414
+ it 'function returns callable object' do
415
+ module LibTest
416
+ extend FFI::Library
417
+ ffi_lib TestLibrary::PATH
418
+ callback :funcptr, [ :int ], :int
419
+ attach_function :testReturnsFunctionPointer, [ ], :funcptr
420
+ end
421
+ f = LibTest.testReturnsFunctionPointer
422
+ expect(f.call(3)).to eq(6)
423
+ end
424
+ end
425
+
426
+ end
427
+
428
+
429
+ describe "Callback with " do
430
+ #
431
+ # Test callbacks that take an argument, returning void
432
+ #
433
+ module LibTest
434
+ extend FFI::Library
435
+ ffi_lib TestLibrary::PATH
436
+
437
+ class S8F32S32 < FFI::Struct
438
+ layout :s8, :char, :f32, :float, :s32, :int
439
+ end
440
+
441
+ callback :cbS8rV, [ :char ], :void
442
+ callback :cbU8rV, [ :uchar ], :void
443
+ callback :cbS16rV, [ :short ], :void
444
+ callback :cbU16rV, [ :ushort ], :void
445
+
446
+ callback :cbZrV, [ :bool ], :void
447
+ callback :cbS32rV, [ :int ], :void
448
+ callback :cbU32rV, [ :uint ], :void
449
+
450
+ callback :cbLrV, [ :long ], :void
451
+ callback :cbULrV, [ :ulong ], :void
452
+ callback :cbArV, [ :string ], :void
453
+ callback :cbPrV, [ :pointer], :void
454
+ callback :cbYrV, [ S8F32S32.ptr ], :void
455
+
456
+ callback :cbS64rV, [ :long_long ], :void
457
+ attach_function :testCallbackCrV, :testClosureBrV, [ :cbS8rV, :char ], :void
458
+ attach_function :testCallbackU8rV, :testClosureBrV, [ :cbU8rV, :uchar ], :void
459
+ attach_function :testCallbackSrV, :testClosureSrV, [ :cbS16rV, :short ], :void
460
+ attach_function :testCallbackU16rV, :testClosureSrV, [ :cbU16rV, :ushort ], :void
461
+ attach_function :testCallbackZrV, :testClosureZrV, [ :cbZrV, :bool ], :void
462
+ attach_function :testCallbackIrV, :testClosureIrV, [ :cbS32rV, :int ], :void
463
+ attach_function :testCallbackU32rV, :testClosureIrV, [ :cbU32rV, :uint ], :void
464
+
465
+ attach_function :testCallbackLrV, :testClosureLrV, [ :cbLrV, :long ], :void
466
+ attach_function :testCallbackULrV, :testClosureULrV, [ :cbULrV, :ulong ], :void
467
+
468
+ attach_function :testCallbackLLrV, :testClosureLLrV, [ :cbS64rV, :long_long ], :void
469
+ attach_function :testCallbackArV, :testClosurePrV, [ :cbArV, :string ], :void
470
+ attach_function :testCallbackPrV, :testClosurePrV, [ :cbPrV, :pointer], :void
471
+ attach_function :testCallbackYrV, :testClosurePrV, [ :cbYrV, S8F32S32.in ], :void
472
+ end
473
+
474
+ it "function with Callback plus another arg should raise error if no arg given" do
475
+ expect { LibTest.testCallbackCrV { |*a| }}.to raise_error
476
+ end
477
+
478
+ it ":char (0) argument" do
479
+ v = 0xdeadbeef
480
+ LibTest.testCallbackCrV(0) { |i| v = i }
481
+ expect(v).to eq(0)
482
+ end
483
+
484
+ it ":char (127) argument" do
485
+ v = 0xdeadbeef
486
+ LibTest.testCallbackCrV(127) { |i| v = i }
487
+ expect(v).to eq(127)
488
+ end
489
+
490
+ it ":char (-128) argument" do
491
+ v = 0xdeadbeef
492
+ LibTest.testCallbackCrV(-128) { |i| v = i }
493
+ expect(v).to eq(-128)
494
+ end
495
+
496
+ it ":char (-1) argument" do
497
+ v = 0xdeadbeef
498
+ LibTest.testCallbackCrV(-1) { |i| v = i }
499
+ expect(v).to eq(-1)
500
+ end
501
+
502
+ it ":uchar (0) argument" do
503
+ v = 0xdeadbeef
504
+ LibTest.testCallbackU8rV(0) { |i| v = i }
505
+ expect(v).to eq(0)
506
+ end
507
+
508
+ it ":uchar (127) argument" do
509
+ v = 0xdeadbeef
510
+ LibTest.testCallbackU8rV(127) { |i| v = i }
511
+ expect(v).to eq(127)
512
+ end
513
+
514
+ it ":uchar (128) argument" do
515
+ v = 0xdeadbeef
516
+ LibTest.testCallbackU8rV(128) { |i| v = i }
517
+ expect(v).to eq(128)
518
+ end
519
+
520
+ it ":uchar (255) argument" do
521
+ v = 0xdeadbeef
522
+ LibTest.testCallbackU8rV(255) { |i| v = i }
523
+ expect(v).to eq(255)
524
+ end
525
+
526
+ it ":short (0) argument" do
527
+ v = 0xdeadbeef
528
+ LibTest.testCallbackSrV(0) { |i| v = i }
529
+ expect(v).to eq(0)
530
+ end
531
+
532
+ it ":short (0x7fff) argument" do
533
+ v = 0xdeadbeef
534
+ LibTest.testCallbackSrV(0x7fff) { |i| v = i }
535
+ expect(v).to eq(0x7fff)
536
+ end
537
+
538
+ it ":short (-0x8000) argument" do
539
+ v = 0xdeadbeef
540
+ LibTest.testCallbackSrV(-0x8000) { |i| v = i }
541
+ expect(v).to eq(-0x8000)
542
+ end
543
+
544
+ it ":short (-1) argument" do
545
+ v = 0xdeadbeef
546
+ LibTest.testCallbackSrV(-1) { |i| v = i }
547
+ expect(v).to eq(-1)
548
+ end
549
+
550
+ it ":ushort (0) argument" do
551
+ v = 0xdeadbeef
552
+ LibTest.testCallbackU16rV(0) { |i| v = i }
553
+ expect(v).to eq(0)
554
+ end
555
+
556
+ it ":ushort (0x7fff) argument" do
557
+ v = 0xdeadbeef
558
+ LibTest.testCallbackU16rV(0x7fff) { |i| v = i }
559
+ expect(v).to eq(0x7fff)
560
+ end
561
+
562
+ it ":ushort (0x8000) argument" do
563
+ v = 0xdeadbeef
564
+ LibTest.testCallbackU16rV(0x8000) { |i| v = i }
565
+ expect(v).to eq(0x8000)
566
+ end
567
+
568
+ it ":ushort (0xffff) argument" do
569
+ v = 0xdeadbeef
570
+ LibTest.testCallbackU16rV(0xffff) { |i| v = i }
571
+ expect(v).to eq(0xffff)
572
+ end
573
+
574
+ it ":bool (true) argument" do
575
+ v = false
576
+ LibTest.testCallbackZrV(true) { |i| v = i }
577
+ expect(v).to be true
578
+ end
579
+
580
+ it ":int (0) argument" do
581
+ v = 0xdeadbeef
582
+ LibTest.testCallbackIrV(0) { |i| v = i }
583
+ expect(v).to eq(0)
584
+ end
585
+
586
+ it ":int (0x7fffffff) argument" do
587
+ v = 0xdeadbeef
588
+ LibTest.testCallbackIrV(0x7fffffff) { |i| v = i }
589
+ expect(v).to eq(0x7fffffff)
590
+ end
591
+
592
+ it ":int (-0x80000000) argument" do
593
+ v = 0xdeadbeef
594
+ LibTest.testCallbackIrV(-0x80000000) { |i| v = i }
595
+ expect(v).to eq(-0x80000000)
596
+ end
597
+
598
+ it ":int (-1) argument" do
599
+ v = 0xdeadbeef
600
+ LibTest.testCallbackIrV(-1) { |i| v = i }
601
+ expect(v).to eq(-1)
602
+ end
603
+
604
+ it ":uint (0) argument" do
605
+ v = 0xdeadbeef
606
+ LibTest.testCallbackU32rV(0) { |i| v = i }
607
+ expect(v).to eq(0)
608
+ end
609
+
610
+ it ":uint (0x7fffffff) argument" do
611
+ v = 0xdeadbeef
612
+ LibTest.testCallbackU32rV(0x7fffffff) { |i| v = i }
613
+ expect(v).to eq(0x7fffffff)
614
+ end
615
+
616
+ it ":uint (0x80000000) argument" do
617
+ v = 0xdeadbeef
618
+ LibTest.testCallbackU32rV(0x80000000) { |i| v = i }
619
+ expect(v).to eq(0x80000000)
620
+ end
621
+
622
+ it ":uint (0xffffffff) argument" do
623
+ v = 0xdeadbeef
624
+ LibTest.testCallbackU32rV(0xffffffff) { |i| v = i }
625
+ expect(v).to eq(0xffffffff)
626
+ end
627
+
628
+ it ":long (0) argument" do
629
+ v = 0xdeadbeef
630
+ LibTest.testCallbackLrV(0) { |i| v = i }
631
+ expect(v).to eq(0)
632
+ end
633
+
634
+ it ":long (0x7fffffff) argument" do
635
+ v = 0xdeadbeef
636
+ LibTest.testCallbackLrV(0x7fffffff) { |i| v = i }
637
+ expect(v).to eq(0x7fffffff)
638
+ end
639
+
640
+ it ":long (-0x80000000) argument" do
641
+ v = 0xdeadbeef
642
+ LibTest.testCallbackLrV(-0x80000000) { |i| v = i }
643
+ expect(v).to eq(-0x80000000)
644
+ end
645
+
646
+ it ":long (-1) argument" do
647
+ v = 0xdeadbeef
648
+ LibTest.testCallbackLrV(-1) { |i| v = i }
649
+ expect(v).to eq(-1)
650
+ end
651
+
652
+ it ":ulong (0) argument" do
653
+ v = 0xdeadbeef
654
+ LibTest.testCallbackULrV(0) { |i| v = i }
655
+ expect(v).to eq(0)
656
+ end
657
+
658
+ it ":ulong (0x7fffffff) argument" do
659
+ v = 0xdeadbeef
660
+ LibTest.testCallbackULrV(0x7fffffff) { |i| v = i }
661
+ expect(v).to eq(0x7fffffff)
662
+ end
663
+
664
+ it ":ulong (0x80000000) argument" do
665
+ v = 0xdeadbeef
666
+ LibTest.testCallbackULrV(0x80000000) { |i| v = i }
667
+ expect(v).to eq(0x80000000)
668
+ end
669
+
670
+ it ":ulong (0xffffffff) argument" do
671
+ v = 0xdeadbeef
672
+ LibTest.testCallbackULrV(0xffffffff) { |i| v = i }
673
+ expect(v).to eq(0xffffffff)
674
+ end
675
+
676
+ it ":long_long (0) argument" do
677
+ v = 0xdeadbeef
678
+ LibTest.testCallbackLLrV(0) { |i| v = i }
679
+ expect(v).to eq(0)
680
+ end
681
+
682
+ it ":long_long (0x7fffffffffffffff) argument" do
683
+ v = 0xdeadbeef
684
+ LibTest.testCallbackLLrV(0x7fffffffffffffff) { |i| v = i }
685
+ expect(v).to eq(0x7fffffffffffffff)
686
+ end
687
+
688
+ it ":long_long (-0x8000000000000000) argument" do
689
+ v = 0xdeadbeef
690
+ LibTest.testCallbackLLrV(-0x8000000000000000) { |i| v = i }
691
+ expect(v).to eq(-0x8000000000000000)
692
+ end
693
+
694
+ it ":long_long (-1) argument" do
695
+ v = 0xdeadbeef
696
+ LibTest.testCallbackLLrV(-1) { |i| v = i }
697
+ expect(v).to eq(-1)
698
+ end
699
+
700
+ it ":string argument" do
701
+ v = nil
702
+ LibTest.testCallbackArV("Hello, World") { |i| v = i }
703
+ expect(v).to eq("Hello, World")
704
+ end
705
+
706
+ it ":string (nil) argument" do
707
+ v = "Hello, World"
708
+ LibTest.testCallbackArV(nil) { |i| v = i }
709
+ expect(v).to be_nil
710
+ end
711
+
712
+ it ":pointer argument" do
713
+ v = nil
714
+ magic = FFI::Pointer.new(0xdeadbeef)
715
+ LibTest.testCallbackPrV(magic) { |i| v = i }
716
+ expect(v).to eq(magic)
717
+ end
718
+
719
+ it ":pointer (nil) argument" do
720
+ v = "Hello, World"
721
+ LibTest.testCallbackPrV(nil) { |i| v = i }
722
+ expect(v).to eq(FFI::Pointer::NULL)
723
+ end
724
+
725
+ it "struct by reference argument" do
726
+ v = nil
727
+ magic = LibTest::S8F32S32.new
728
+ LibTest.testCallbackYrV(magic) { |i| v = i }
729
+ expect(v.class).to eq(magic.class)
730
+ expect(v.pointer).to eq(magic.pointer)
731
+ end
732
+
733
+ it "struct by reference argument with nil value" do
734
+ v = LibTest::S8F32S32.new
735
+ LibTest.testCallbackYrV(nil) { |i| v = i }
736
+ expect(v.is_a?(FFI::Struct)).to be true
737
+ expect(v.pointer).to eq(FFI::Pointer::NULL)
738
+ end
739
+
740
+ it "varargs parameters are rejected" do
741
+ expect {
742
+ Module.new do
743
+ extend FFI::Library
744
+ ffi_lib TestLibrary::PATH
745
+ callback :cbVrL, [ :varargs ], :long
746
+ end
747
+ }.to raise_error(ArgumentError)
748
+ end
749
+
750
+ #
751
+ # Test stdcall convention with function and callback.
752
+ # This is Windows 32-bit only.
753
+ #
754
+ if FFI::Platform::OS =~ /windows|cygwin/ && FFI::Platform::ARCH == 'i386'
755
+ module LibTestStdcall
756
+ extend FFI::Library
757
+ ffi_lib TestLibrary::PATH
758
+ ffi_convention :stdcall
759
+
760
+ callback :cbStdcall, [ :pointer, :long ], :void
761
+ attach_function :testCallbackStdcall, 'testClosureStdcall', [ :pointer, :cbStdcall, :long ], :bool
762
+ end
763
+
764
+ it "stdcall convention" do
765
+ v = 0xdeadbeef
766
+ po = FFI::MemoryPointer.new :long
767
+ pr = proc{|a,i| v = a,i; i }
768
+ res = LibTestStdcall.testCallbackStdcall(po, pr, 0x7fffffff)
769
+ expect(v).to eq([po, 0x7fffffff])
770
+ expect(res).to be true
771
+ end
772
+ end
773
+ end