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,352 @@
1
+ /*
2
+ * Copyright (c) 2010 Wayne Meissner
3
+ *
4
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of the Ruby FFI project nor the
15
+ * names of its contributors may be used to endorse or promote products
16
+ * derived from this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #ifndef _MSC_VER
31
+ #include <stdbool.h>
32
+ #else
33
+ # include "win32/stdbool.h"
34
+ # include "win32/stdint.h"
35
+ #endif
36
+
37
+ #if defined(__CYGWIN__) || !defined(_WIN32)
38
+ # include <pthread.h>
39
+ # include <errno.h>
40
+ # include <signal.h>
41
+ # include <unistd.h>
42
+ #else
43
+ # include <winsock2.h>
44
+ # define _WINSOCKAPI_
45
+ # include <windows.h>
46
+ #endif
47
+ #include <fcntl.h>
48
+ #include "Thread.h"
49
+
50
+ #ifdef _WIN32
51
+ static volatile DWORD frame_thread_key = TLS_OUT_OF_INDEXES;
52
+ #else
53
+ static pthread_key_t thread_data_key;
54
+ struct thread_data {
55
+ rbffi_frame_t* frame;
56
+ };
57
+ static inline struct thread_data* thread_data_get(void);
58
+
59
+ #endif
60
+
61
+ rbffi_frame_t*
62
+ rbffi_frame_current(void)
63
+ {
64
+ #ifdef _WIN32
65
+ return (rbffi_frame_t *) TlsGetValue(frame_thread_key);
66
+ #else
67
+ struct thread_data* td = (struct thread_data *) pthread_getspecific(thread_data_key);
68
+ return td != NULL ? td->frame : NULL;
69
+ #endif
70
+ }
71
+
72
+ void
73
+ rbffi_frame_push(rbffi_frame_t* frame)
74
+ {
75
+ memset(frame, 0, sizeof(*frame));
76
+ frame->has_gvl = true;
77
+ frame->exc = Qnil;
78
+
79
+ #ifdef _WIN32
80
+ frame->prev = TlsGetValue(frame_thread_key);
81
+ TlsSetValue(frame_thread_key, frame);
82
+ #else
83
+ frame->td = thread_data_get();
84
+ frame->prev = frame->td->frame;
85
+ frame->td->frame = frame;
86
+ #endif
87
+ }
88
+
89
+ void
90
+ rbffi_frame_pop(rbffi_frame_t* frame)
91
+ {
92
+ #ifdef _WIN32
93
+ TlsSetValue(frame_thread_key, frame->prev);
94
+ #else
95
+ frame->td->frame = frame->prev;
96
+ #endif
97
+ }
98
+
99
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
100
+
101
+ #if !defined(_WIN32)
102
+
103
+ struct BlockingThread {
104
+ pthread_t tid;
105
+ VALUE (*fn)(void *);
106
+ void *data;
107
+ void (*ubf)(void *);
108
+ void *data2;
109
+ VALUE retval;
110
+ int wrfd;
111
+ int rdfd;
112
+ };
113
+
114
+ static void*
115
+ rbffi_blocking_thread(void* args)
116
+ {
117
+ struct BlockingThread* thr = (struct BlockingThread *) args;
118
+ char c = 1;
119
+ VALUE retval;
120
+
121
+ retval = (*thr->fn)(thr->data);
122
+
123
+ pthread_testcancel();
124
+
125
+ thr->retval = retval;
126
+
127
+ write(thr->wrfd, &c, sizeof(c));
128
+
129
+ return NULL;
130
+ }
131
+
132
+ static VALUE
133
+ wait_for_thread(void *data)
134
+ {
135
+ struct BlockingThread* thr = (struct BlockingThread *) data;
136
+ char c;
137
+
138
+ if (read(thr->rdfd, &c, 1) < 1) {
139
+ rb_thread_wait_fd(thr->rdfd);
140
+ while (read(thr->rdfd, &c, 1) < 1 && rb_io_wait_readable(thr->rdfd) == Qtrue) {
141
+ ;
142
+ }
143
+ }
144
+
145
+ return Qnil;
146
+ }
147
+
148
+ static VALUE
149
+ cleanup_blocking_thread(void *data, VALUE exc)
150
+ {
151
+ struct BlockingThread* thr = (struct BlockingThread *) data;
152
+
153
+ if (thr->ubf != (void (*)(void *)) -1) {
154
+ (*thr->ubf)(thr->data2);
155
+ } else {
156
+ pthread_kill(thr->tid, SIGVTALRM);
157
+ }
158
+
159
+ return exc;
160
+ }
161
+
162
+ VALUE
163
+ rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2)
164
+ {
165
+ struct BlockingThread* thr;
166
+ int fd[2];
167
+ VALUE exc;
168
+
169
+ if (pipe(fd) < 0) {
170
+ rb_raise(rb_eSystemCallError, "pipe(2) failed");
171
+ return Qnil;
172
+ }
173
+ fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL) | O_NONBLOCK);
174
+
175
+ thr = ALLOC_N(struct BlockingThread, 1);
176
+ thr->rdfd = fd[0];
177
+ thr->wrfd = fd[1];
178
+ thr->fn = func;
179
+ thr->data = data1;
180
+ thr->ubf = ubf;
181
+ thr->data2 = data2;
182
+ thr->retval = Qnil;
183
+
184
+ if (pthread_create(&thr->tid, NULL, rbffi_blocking_thread, thr) != 0) {
185
+ close(fd[0]);
186
+ close(fd[1]);
187
+ xfree(thr);
188
+ rb_raise(rb_eSystemCallError, "pipe(2) failed");
189
+ return Qnil;
190
+ }
191
+
192
+ exc = rb_rescue2(wait_for_thread, (VALUE) thr, cleanup_blocking_thread, (VALUE) thr,
193
+ rb_eException);
194
+
195
+ pthread_join(thr->tid, NULL);
196
+ close(fd[1]);
197
+ close(fd[0]);
198
+ xfree(thr);
199
+
200
+ if (exc != Qnil) {
201
+ rb_exc_raise(exc);
202
+ }
203
+
204
+ return thr->retval;
205
+ }
206
+
207
+ #else
208
+ /* win32 implementation */
209
+
210
+ struct BlockingThread {
211
+ HANDLE tid;
212
+ VALUE (*fn)(void *);
213
+ void *data;
214
+ void (*ubf)(void *);
215
+ void *data2;
216
+ VALUE retval;
217
+ int wrfd;
218
+ int rdfd;
219
+ };
220
+
221
+ static DWORD __stdcall
222
+ rbffi_blocking_thread(LPVOID args)
223
+ {
224
+ struct BlockingThread* thr = (struct BlockingThread *) args;
225
+ char c = 1;
226
+ VALUE retval;
227
+
228
+ retval = (*thr->fn)(thr->data);
229
+ thr->retval = retval;
230
+
231
+ write(thr->wrfd, &c, sizeof(c));
232
+
233
+ return 0;
234
+ }
235
+
236
+ static VALUE
237
+ wait_for_thread(void *data)
238
+ {
239
+ struct BlockingThread* thr = (struct BlockingThread *) data;
240
+ char c, res;
241
+ fd_set rfds;
242
+
243
+ FD_ZERO(&rfds);
244
+ FD_SET(thr->rdfd, &rfds);
245
+ rb_thread_select(thr->rdfd + 1, &rfds, NULL, NULL, NULL);
246
+ read(thr->rdfd, &c, 1);
247
+ return Qnil;
248
+ }
249
+
250
+ static VALUE
251
+ cleanup_blocking_thread(void *data, VALUE exc)
252
+ {
253
+ struct BlockingThread* thr = (struct BlockingThread *) data;
254
+
255
+ if (thr->ubf != (void (*)(void *)) -1) {
256
+ (*thr->ubf)(thr->data2);
257
+ } else {
258
+ TerminateThread(thr->tid, 0);
259
+ }
260
+
261
+ return exc;
262
+ }
263
+
264
+ VALUE
265
+ rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2)
266
+ {
267
+ struct BlockingThread* thr;
268
+ int fd[2];
269
+ VALUE exc;
270
+ DWORD state;
271
+ DWORD res;
272
+
273
+ if (_pipe(fd, 1024, O_BINARY) == -1) {
274
+ rb_raise(rb_eSystemCallError, "_pipe() failed");
275
+ return Qnil;
276
+ }
277
+
278
+ thr = ALLOC_N(struct BlockingThread, 1);
279
+ thr->rdfd = fd[0];
280
+ thr->wrfd = fd[1];
281
+ thr->fn = func;
282
+ thr->data = data1;
283
+ thr->ubf = ubf;
284
+ thr->data2 = data2;
285
+ thr->retval = Qnil;
286
+
287
+ thr->tid = CreateThread(NULL, 0, rbffi_blocking_thread, thr, 0, NULL);
288
+ if (!thr->tid) {
289
+ close(fd[0]);
290
+ close(fd[1]);
291
+ xfree(thr);
292
+ rb_raise(rb_eSystemCallError, "CreateThread() failed");
293
+ return Qnil;
294
+ }
295
+
296
+ exc = rb_rescue2(wait_for_thread, (VALUE) thr, cleanup_blocking_thread, (VALUE) thr,
297
+ rb_eException);
298
+
299
+ /* The thread should be finished, already. */
300
+ WaitForSingleObject(thr->tid, INFINITE);
301
+ CloseHandle(thr->tid);
302
+ close(fd[1]);
303
+ close(fd[0]);
304
+ xfree(thr);
305
+
306
+ if (exc != Qnil) {
307
+ rb_exc_raise(exc);
308
+ }
309
+
310
+ return thr->retval;
311
+ }
312
+
313
+ #endif /* !_WIN32 */
314
+
315
+ #endif /* HAVE_RB_THREAD_BLOCKING_REGION */
316
+
317
+ #ifndef _WIN32
318
+ static struct thread_data* thread_data_init(void);
319
+
320
+ static inline struct thread_data*
321
+ thread_data_get(void)
322
+ {
323
+ struct thread_data* td = (struct thread_data *) pthread_getspecific(thread_data_key);
324
+ return td != NULL ? td : thread_data_init();
325
+ }
326
+
327
+ static struct thread_data*
328
+ thread_data_init(void)
329
+ {
330
+ struct thread_data* td = calloc(1, sizeof(struct thread_data));
331
+
332
+ pthread_setspecific(thread_data_key, td);
333
+
334
+ return td;
335
+ }
336
+
337
+ static void
338
+ thread_data_free(void *ptr)
339
+ {
340
+ free(ptr);
341
+ }
342
+ #endif
343
+
344
+ void
345
+ rbffi_Thread_Init(VALUE moduleFFI)
346
+ {
347
+ #ifdef _WIN32
348
+ frame_thread_key = TlsAlloc();
349
+ #else
350
+ pthread_key_create(&thread_data_key, thread_data_free);
351
+ #endif
352
+ }
@@ -0,0 +1,95 @@
1
+ /*
2
+ * Copyright (c) 2010 Wayne Meissner
3
+ *
4
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of the Ruby FFI project nor the
15
+ * names of its contributors may be used to endorse or promote products
16
+ * derived from this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #ifndef RBFFI_THREAD_H
31
+ #define RBFFI_THREAD_H
32
+
33
+ #ifndef _MSC_VER
34
+ # include <stdbool.h>
35
+ #else
36
+ # include "win32/stdbool.h"
37
+ # include "win32/stdint.h"
38
+ #endif
39
+ #include <ruby.h>
40
+ #include "extconf.h"
41
+
42
+ #ifdef __cplusplus
43
+ extern "C" {
44
+ #endif
45
+
46
+
47
+ #ifdef _WIN32
48
+ # include <windows.h>
49
+ #else
50
+ # include <pthread.h>
51
+ #endif
52
+
53
+ typedef struct {
54
+ #ifdef _WIN32
55
+ DWORD id;
56
+ #else
57
+ pthread_t id;
58
+ #endif
59
+ bool valid;
60
+ bool has_gvl;
61
+ VALUE exc;
62
+ } rbffi_thread_t;
63
+
64
+ typedef struct rbffi_frame {
65
+ #ifndef _WIN32
66
+ struct thread_data* td;
67
+ #endif
68
+ struct rbffi_frame* prev;
69
+ bool has_gvl;
70
+ VALUE exc;
71
+ } rbffi_frame_t;
72
+
73
+ rbffi_frame_t* rbffi_frame_current(void);
74
+ void rbffi_frame_push(rbffi_frame_t* frame);
75
+ void rbffi_frame_pop(rbffi_frame_t* frame);
76
+
77
+ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
78
+ # define rbffi_thread_blocking_region rb_thread_call_without_gvl
79
+
80
+ #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
81
+ # define rbffi_thread_blocking_region rb_thread_blocking_region
82
+
83
+ #else
84
+
85
+ VALUE rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2);
86
+
87
+ #endif
88
+
89
+
90
+ #ifdef __cplusplus
91
+ }
92
+ #endif
93
+
94
+ #endif /* RBFFI_THREAD_H */
95
+
@@ -0,0 +1,397 @@
1
+ /*
2
+ * Copyright (c) 2009, Wayne Meissner
3
+ *
4
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of the Ruby FFI project nor the
15
+ * names of its contributors may be used to endorse or promote products
16
+ * derived from this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #ifndef _MSC_VER
31
+ #include <sys/param.h>
32
+ #endif
33
+
34
+ #include <sys/types.h>
35
+ #include <ruby.h>
36
+ #include <ffi.h>
37
+ #include "rbffi.h"
38
+ #include "compat.h"
39
+ #include "Types.h"
40
+ #include "Type.h"
41
+
42
+
43
+ typedef struct BuiltinType_ {
44
+ Type type;
45
+ char* name;
46
+ } BuiltinType;
47
+
48
+ static void builtin_type_free(BuiltinType *);
49
+
50
+ VALUE rbffi_TypeClass = Qnil;
51
+
52
+ static VALUE classBuiltinType = Qnil;
53
+ static VALUE moduleNativeType = Qnil;
54
+ static VALUE typeMap = Qnil, sizeMap = Qnil;
55
+ static ID id_find_type = 0, id_type_size = 0, id_size = 0;
56
+
57
+ static VALUE
58
+ type_allocate(VALUE klass)
59
+ {
60
+ Type* type;
61
+ VALUE obj = Data_Make_Struct(klass, Type, NULL, -1, type);
62
+
63
+ type->nativeType = -1;
64
+ type->ffiType = &ffi_type_void;
65
+
66
+ return obj;
67
+ }
68
+
69
+ /*
70
+ * Document-method: initialize
71
+ * call-seq: initialize(value)
72
+ * @param [Fixnum,Type] value
73
+ * @return [self]
74
+ */
75
+ static VALUE
76
+ type_initialize(VALUE self, VALUE value)
77
+ {
78
+ Type* type;
79
+ Type* other;
80
+
81
+ Data_Get_Struct(self, Type, type);
82
+
83
+ if (FIXNUM_P(value)) {
84
+ type->nativeType = FIX2INT(value);
85
+ } else if (rb_obj_is_kind_of(value, rbffi_TypeClass)) {
86
+ Data_Get_Struct(value, Type, other);
87
+ type->nativeType = other->nativeType;
88
+ type->ffiType = other->ffiType;
89
+ } else {
90
+ rb_raise(rb_eArgError, "wrong type");
91
+ }
92
+
93
+ return self;
94
+ }
95
+
96
+ /*
97
+ * call-seq: type.size
98
+ * @return [Fixnum]
99
+ * Return type's size, in bytes.
100
+ */
101
+ static VALUE
102
+ type_size(VALUE self)
103
+ {
104
+ Type *type;
105
+
106
+ Data_Get_Struct(self, Type, type);
107
+
108
+ return INT2FIX(type->ffiType->size);
109
+ }
110
+
111
+ /*
112
+ * call-seq: type.alignment
113
+ * @return [Fixnum]
114
+ * Get Type alignment.
115
+ */
116
+ static VALUE
117
+ type_alignment(VALUE self)
118
+ {
119
+ Type *type;
120
+
121
+ Data_Get_Struct(self, Type, type);
122
+
123
+ return INT2FIX(type->ffiType->alignment);
124
+ }
125
+
126
+ /*
127
+ * call-seq: type.inspect
128
+ * @return [String]
129
+ * Inspect {Type} object.
130
+ */
131
+ static VALUE
132
+ type_inspect(VALUE self)
133
+ {
134
+ char buf[100];
135
+ Type *type;
136
+
137
+ Data_Get_Struct(self, Type, type);
138
+
139
+ snprintf(buf, sizeof(buf), "#<%s:%p size=%d alignment=%d>",
140
+ rb_obj_classname(self), type, (int) type->ffiType->size, (int) type->ffiType->alignment);
141
+
142
+ return rb_str_new2(buf);
143
+ }
144
+
145
+ static VALUE
146
+ builtin_type_new(VALUE klass, int nativeType, ffi_type* ffiType, const char* name)
147
+ {
148
+ BuiltinType* type;
149
+ VALUE obj = Qnil;
150
+
151
+ obj = Data_Make_Struct(klass, BuiltinType, NULL, builtin_type_free, type);
152
+
153
+ type->name = strdup(name);
154
+ type->type.nativeType = nativeType;
155
+ type->type.ffiType = ffiType;
156
+
157
+ return obj;
158
+ }
159
+
160
+ static void
161
+ builtin_type_free(BuiltinType *type)
162
+ {
163
+ free(type->name);
164
+ xfree(type);
165
+ }
166
+
167
+ /*
168
+ * call-seq: type.inspect
169
+ * @return [String]
170
+ * Inspect {Type::Builtin} object.
171
+ */
172
+ static VALUE
173
+ builtin_type_inspect(VALUE self)
174
+ {
175
+ char buf[100];
176
+ BuiltinType *type;
177
+
178
+ Data_Get_Struct(self, BuiltinType, type);
179
+ snprintf(buf, sizeof(buf), "#<%s:%s size=%d alignment=%d>",
180
+ rb_obj_classname(self), type->name, (int) type->type.ffiType->size, type->type.ffiType->alignment);
181
+
182
+ return rb_str_new2(buf);
183
+ }
184
+
185
+ int
186
+ rbffi_type_size(VALUE type)
187
+ {
188
+ int t = TYPE(type);
189
+
190
+ if (t == T_FIXNUM || t == T_BIGNUM) {
191
+ return NUM2INT(type);
192
+
193
+ } else if (t == T_SYMBOL) {
194
+ /*
195
+ * Try looking up directly in the type and size maps
196
+ */
197
+ VALUE nType;
198
+ if ((nType = rb_hash_lookup(typeMap, type)) != Qnil) {
199
+ if (rb_obj_is_kind_of(nType, rbffi_TypeClass)) {
200
+ Type* type;
201
+ Data_Get_Struct(nType, Type, type);
202
+ return (int) type->ffiType->size;
203
+
204
+ } else if (rb_respond_to(nType, id_size)) {
205
+ return NUM2INT(rb_funcall2(nType, id_size, 0, NULL));
206
+ }
207
+ }
208
+
209
+ /* Not found - call up to the ruby version to resolve */
210
+ return NUM2INT(rb_funcall2(rbffi_FFIModule, id_type_size, 1, &type));
211
+
212
+ } else {
213
+ return NUM2INT(rb_funcall2(type, id_size, 0, NULL));
214
+ }
215
+ }
216
+
217
+ VALUE
218
+ rbffi_Type_Lookup(VALUE name)
219
+ {
220
+ int t = TYPE(name);
221
+ if (t == T_SYMBOL || t == T_STRING) {
222
+ /*
223
+ * Try looking up directly in the type Map
224
+ */
225
+ VALUE nType;
226
+ if ((nType = rb_hash_lookup(typeMap, name)) != Qnil && rb_obj_is_kind_of(nType, rbffi_TypeClass)) {
227
+ return nType;
228
+ }
229
+ } else if (rb_obj_is_kind_of(name, rbffi_TypeClass)) {
230
+
231
+ return name;
232
+ }
233
+
234
+ /* Nothing found - let caller handle raising exceptions */
235
+ return Qnil;
236
+ }
237
+
238
+ /**
239
+ * rbffi_Type_Find() is like rbffi_Type_Lookup, but an error is raised if the
240
+ * type is not found.
241
+ */
242
+ VALUE
243
+ rbffi_Type_Find(VALUE name)
244
+ {
245
+ VALUE rbType = rbffi_Type_Lookup(name);
246
+
247
+ if (!RTEST(rbType)) {
248
+ VALUE s = rb_inspect(name);
249
+ rb_raise(rb_eTypeError, "invalid type, %s", RSTRING_PTR(s));
250
+ RB_GC_GUARD(s);
251
+ }
252
+
253
+ return rbType;
254
+ }
255
+
256
+ void
257
+ rbffi_Type_Init(VALUE moduleFFI)
258
+ {
259
+ /*
260
+ * Document-class: FFI::Type
261
+ * This class manages C types.
262
+ *
263
+ * It embbed {FFI::Type::Builtin} objects as constants (for names,
264
+ * see {FFI::NativeType}).
265
+ */
266
+ rbffi_TypeClass = rb_define_class_under(moduleFFI, "Type", rb_cObject);
267
+
268
+ /*
269
+ * Document-constant: FFI::TypeDefs
270
+ */
271
+ rb_define_const(moduleFFI, "TypeDefs", typeMap = rb_hash_new());
272
+ rb_define_const(moduleFFI, "SizeTypes", sizeMap = rb_hash_new());
273
+ rb_global_variable(&typeMap);
274
+ rb_global_variable(&sizeMap);
275
+ id_find_type = rb_intern("find_type");
276
+ id_type_size = rb_intern("type_size");
277
+ id_size = rb_intern("size");
278
+
279
+ /*
280
+ * Document-class: FFI::Type::Builtin
281
+ * Class for Built-in types.
282
+ */
283
+ classBuiltinType = rb_define_class_under(rbffi_TypeClass, "Builtin", rbffi_TypeClass);
284
+ /*
285
+ * Document-module: FFI::NativeType
286
+ * This module defines constants for native (C) types.
287
+ *
288
+ * ==Native type constants
289
+ * Native types are defined by constants :
290
+ * * INT8, SCHAR, CHAR
291
+ * * UINT8, UCHAR
292
+ * * INT16, SHORT, SSHORT
293
+ * * UINT16, USHORT
294
+ * * INT32,, INT, SINT
295
+ * * UINT32, UINT
296
+ * * INT64, LONG_LONG, SLONG_LONG
297
+ * * UINT64, ULONG_LONG
298
+ * * LONG, SLONG
299
+ * * ULONG
300
+ * * FLOAT32, FLOAT
301
+ * * FLOAT64, DOUBLE
302
+ * * POINTER
303
+ * * CALLBACK
304
+ * * FUNCTION
305
+ * * CHAR_ARRAY
306
+ * * BOOL
307
+ * * STRING (immutable string, nul terminated)
308
+ * * STRUCT (struct-b-value param or result)
309
+ * * ARRAY (array type definition)
310
+ * * MAPPED (custom native type)
311
+ * For function return type only :
312
+ * * VOID
313
+ * For function argument type only :
314
+ * * BUFFER_IN
315
+ * * BUFFER_OUT
316
+ * * VARARGS (function takes a variable number of arguments)
317
+ *
318
+ * All these constants are exported to {FFI} module prefixed with "TYPE_".
319
+ * They are objets from {FFI::Type::Builtin} class.
320
+ */
321
+ moduleNativeType = rb_define_module_under(moduleFFI, "NativeType");
322
+
323
+ /*
324
+ * Document-global: FFI::Type
325
+ */
326
+ rb_global_variable(&rbffi_TypeClass);
327
+ rb_global_variable(&classBuiltinType);
328
+ rb_global_variable(&moduleNativeType);
329
+
330
+ rb_define_alloc_func(rbffi_TypeClass, type_allocate);
331
+ rb_define_method(rbffi_TypeClass, "initialize", type_initialize, 1);
332
+ rb_define_method(rbffi_TypeClass, "size", type_size, 0);
333
+ rb_define_method(rbffi_TypeClass, "alignment", type_alignment, 0);
334
+ rb_define_method(rbffi_TypeClass, "inspect", type_inspect, 0);
335
+
336
+ /* Make Type::Builtin non-allocatable */
337
+ rb_undef_method(CLASS_OF(classBuiltinType), "new");
338
+ rb_define_method(classBuiltinType, "inspect", builtin_type_inspect, 0);
339
+
340
+ rb_global_variable(&rbffi_TypeClass);
341
+ rb_global_variable(&classBuiltinType);
342
+
343
+ /* Define all the builtin types */
344
+ #define T(x, ffiType) do { \
345
+ VALUE t = Qnil; \
346
+ rb_define_const(rbffi_TypeClass, #x, t = builtin_type_new(classBuiltinType, NATIVE_##x, ffiType, #x)); \
347
+ rb_define_const(moduleNativeType, #x, t); \
348
+ rb_define_const(moduleFFI, "TYPE_" #x, t); \
349
+ } while(0)
350
+
351
+ #define A(old_type, new_type) do { \
352
+ VALUE t = rb_const_get(rbffi_TypeClass, rb_intern(#old_type)); \
353
+ rb_const_set(rbffi_TypeClass, rb_intern(#new_type), t); \
354
+ } while(0)
355
+
356
+ /*
357
+ * Document-constant: FFI::Type::Builtin::VOID
358
+ */
359
+ T(VOID, &ffi_type_void);
360
+ T(INT8, &ffi_type_sint8);
361
+ A(INT8, SCHAR);
362
+ A(INT8, CHAR);
363
+ T(UINT8, &ffi_type_uint8);
364
+ A(UINT8, UCHAR);
365
+
366
+ T(INT16, &ffi_type_sint16);
367
+ A(INT16, SHORT);
368
+ A(INT16, SSHORT);
369
+ T(UINT16, &ffi_type_uint16);
370
+ A(UINT16, USHORT);
371
+ T(INT32, &ffi_type_sint32);
372
+ A(INT32, INT);
373
+ A(INT32, SINT);
374
+ T(UINT32, &ffi_type_uint32);
375
+ A(UINT32, UINT);
376
+ T(INT64, &ffi_type_sint64);
377
+ A(INT64, LONG_LONG);
378
+ A(INT64, SLONG_LONG);
379
+ T(UINT64, &ffi_type_uint64);
380
+ A(UINT64, ULONG_LONG);
381
+ T(LONG, &ffi_type_slong);
382
+ A(LONG, SLONG);
383
+ T(ULONG, &ffi_type_ulong);
384
+ T(FLOAT32, &ffi_type_float);
385
+ A(FLOAT32, FLOAT);
386
+ T(FLOAT64, &ffi_type_double);
387
+ A(FLOAT64, DOUBLE);
388
+ T(LONGDOUBLE, &ffi_type_longdouble);
389
+ T(POINTER, &ffi_type_pointer);
390
+ T(STRING, &ffi_type_pointer);
391
+ T(BUFFER_IN, &ffi_type_pointer);
392
+ T(BUFFER_OUT, &ffi_type_pointer);
393
+ T(BUFFER_INOUT, &ffi_type_pointer);
394
+ T(BOOL, &ffi_type_uchar);
395
+ T(VARARGS, &ffi_type_void);
396
+ }
397
+