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,62 @@
1
+ /*
2
+ * Copyright (c) 2009, Wayne Meissner
3
+ * Copyright (C) 2009 Luc Heinrich <luc@honk-honk.com>
4
+ *
5
+ * This file is part of ruby-ffi.
6
+ *
7
+ * All rights reserved.
8
+ *
9
+ * Redistribution and use in source and binary forms, with or without
10
+ * modification, are permitted provided that the following conditions are met:
11
+ *
12
+ * * Redistributions of source code must retain the above copyright notice, this
13
+ * list of conditions and the following disclaimer.
14
+ * * Redistributions in binary form must reproduce the above copyright notice
15
+ * this list of conditions and the following disclaimer in the documentation
16
+ * and/or other materials provided with the distribution.
17
+ * * Neither the name of the Evan Phoenix nor the names of its contributors
18
+ * may be used to endorse or promote products derived from this software
19
+ * without specific prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
25
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ *
32
+ */
33
+
34
+ #ifndef RBFFI_TYPE_H
35
+ #define RBFFI_TYPE_H
36
+
37
+ #include <ruby.h>
38
+ #include <ffi.h>
39
+
40
+ #ifdef __cplusplus
41
+ extern "C" {
42
+ #endif
43
+
44
+ typedef struct Type_ Type;
45
+
46
+ #include "Types.h"
47
+
48
+ struct Type_ {
49
+ NativeType nativeType;
50
+ ffi_type* ffiType;
51
+ };
52
+
53
+ extern VALUE rbffi_TypeClass;
54
+ extern VALUE rbffi_Type_Lookup(VALUE type);
55
+ extern VALUE rbffi_Type_Find(VALUE type);
56
+
57
+ #ifdef __cplusplus
58
+ }
59
+ #endif
60
+
61
+ #endif /* RBFFI_TYPE_H */
62
+
@@ -0,0 +1,139 @@
1
+ /*
2
+ * Copyright (c) 2009, Wayne Meissner
3
+ * Copyright (c) 2009, Luc Heinrich
4
+ * Copyright (c) 2009, Aman Gupta.
5
+ *
6
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
7
+ * All rights reserved.
8
+ *
9
+ * Redistribution and use in source and binary forms, with or without
10
+ * modification, are permitted provided that the following conditions are met:
11
+ * * Redistributions of source code must retain the above copyright
12
+ * notice, this list of conditions and the following disclaimer.
13
+ * * Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ * * Neither the name of the Ruby FFI project nor the
17
+ * names of its contributors may be used to endorse or promote products
18
+ * derived from this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
24
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+
32
+ #include <ruby.h>
33
+ #include "Pointer.h"
34
+ #include "rbffi.h"
35
+ #include "Function.h"
36
+ #include "StructByValue.h"
37
+ #include "Types.h"
38
+ #include "Struct.h"
39
+ #include "MappedType.h"
40
+ #include "MemoryPointer.h"
41
+ #include "LongDouble.h"
42
+
43
+ static ID id_from_native = 0;
44
+
45
+
46
+ VALUE
47
+ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr)
48
+ {
49
+ switch (type->nativeType) {
50
+ case NATIVE_VOID:
51
+ return Qnil;
52
+ case NATIVE_INT8:
53
+ return INT2NUM((signed char) *(ffi_sarg *) ptr);
54
+ case NATIVE_INT16:
55
+ return INT2NUM((signed short) *(ffi_sarg *) ptr);
56
+ case NATIVE_INT32:
57
+ return INT2NUM((signed int) *(ffi_sarg *) ptr);
58
+ case NATIVE_LONG:
59
+ return LONG2NUM((signed long) *(ffi_sarg *) ptr);
60
+ case NATIVE_INT64:
61
+ return LL2NUM(*(signed long long *) ptr);
62
+
63
+ case NATIVE_UINT8:
64
+ return UINT2NUM((unsigned char) *(ffi_arg *) ptr);
65
+ case NATIVE_UINT16:
66
+ return UINT2NUM((unsigned short) *(ffi_arg *) ptr);
67
+ case NATIVE_UINT32:
68
+ return UINT2NUM((unsigned int) *(ffi_arg *) ptr);
69
+ case NATIVE_ULONG:
70
+ return ULONG2NUM((unsigned long) *(ffi_arg *) ptr);
71
+ case NATIVE_UINT64:
72
+ return ULL2NUM(*(unsigned long long *) ptr);
73
+
74
+ case NATIVE_FLOAT32:
75
+ return rb_float_new(*(float *) ptr);
76
+ case NATIVE_FLOAT64:
77
+ return rb_float_new(*(double *) ptr);
78
+
79
+ case NATIVE_LONGDOUBLE:
80
+ return rbffi_longdouble_new(*(long double *) ptr);
81
+
82
+ case NATIVE_STRING:
83
+ return (*(void **) ptr != NULL) ? rb_tainted_str_new2(*(char **) ptr) : Qnil;
84
+ case NATIVE_POINTER:
85
+ return rbffi_Pointer_NewInstance(*(void **) ptr);
86
+ case NATIVE_BOOL:
87
+ return ((unsigned char) *(ffi_arg *) ptr) ? Qtrue : Qfalse;
88
+
89
+ case NATIVE_FUNCTION:
90
+ case NATIVE_CALLBACK: {
91
+ return *(void **) ptr != NULL
92
+ ? rbffi_Function_NewInstance(rbType, rbffi_Pointer_NewInstance(*(void **) ptr))
93
+ : Qnil;
94
+ }
95
+
96
+ case NATIVE_STRUCT: {
97
+ StructByValue* sbv = (StructByValue *)type;
98
+ AbstractMemory* mem;
99
+ VALUE rbMemory = rbffi_MemoryPointer_NewInstance(1, sbv->base.ffiType->size, false);
100
+
101
+ Data_Get_Struct(rbMemory, AbstractMemory, mem);
102
+ memcpy(mem->address, ptr, sbv->base.ffiType->size);
103
+ RB_GC_GUARD(rbMemory);
104
+ RB_GC_GUARD(rbType);
105
+
106
+ return rb_class_new_instance(1, &rbMemory, sbv->rbStructClass);
107
+ }
108
+
109
+ case NATIVE_MAPPED: {
110
+ /*
111
+ * For mapped types, first convert to the real native type, then upcall to
112
+ * ruby to convert to the expected return type
113
+ */
114
+ MappedType* m = (MappedType *) type;
115
+ VALUE values[2], rbReturnValue;
116
+
117
+ values[0] = rbffi_NativeValue_ToRuby(m->type, m->rbType, ptr);
118
+ values[1] = Qnil;
119
+
120
+
121
+ rbReturnValue = rb_funcall2(m->rbConverter, id_from_native, 2, values);
122
+ RB_GC_GUARD(values[0]);
123
+ RB_GC_GUARD(rbType);
124
+
125
+ return rbReturnValue;
126
+ }
127
+
128
+ default:
129
+ rb_raise(rb_eRuntimeError, "Unknown type: %d", type->nativeType);
130
+ return Qnil;
131
+ }
132
+ }
133
+
134
+ void
135
+ rbffi_Types_Init(VALUE moduleFFI)
136
+ {
137
+ id_from_native = rb_intern("from_native");
138
+ }
139
+
@@ -0,0 +1,89 @@
1
+ /*
2
+ * Copyright (c) 2008, 2009, Wayne Meissner
3
+ * Copyright (c) 2009, Luc Heinrich <luc@honk-honk.com>
4
+ *
5
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ * * Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ * * Neither the name of the Ruby FFI project nor the
16
+ * names of its contributors may be used to endorse or promote products
17
+ * derived from this software without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #ifndef RBFFI_TYPES_H
32
+ #define RBFFI_TYPES_H
33
+
34
+ #ifdef __cplusplus
35
+ extern "C" {
36
+ #endif
37
+
38
+ typedef enum {
39
+ NATIVE_VOID,
40
+ NATIVE_INT8,
41
+ NATIVE_UINT8,
42
+ NATIVE_INT16,
43
+ NATIVE_UINT16,
44
+ NATIVE_INT32,
45
+ NATIVE_UINT32,
46
+ NATIVE_INT64,
47
+ NATIVE_UINT64,
48
+ NATIVE_LONG,
49
+ NATIVE_ULONG,
50
+ NATIVE_FLOAT32,
51
+ NATIVE_FLOAT64,
52
+ NATIVE_LONGDOUBLE,
53
+ NATIVE_POINTER,
54
+ NATIVE_CALLBACK,
55
+ NATIVE_FUNCTION,
56
+ NATIVE_BUFFER_IN,
57
+ NATIVE_BUFFER_OUT,
58
+ NATIVE_BUFFER_INOUT,
59
+ NATIVE_CHAR_ARRAY,
60
+ NATIVE_BOOL,
61
+
62
+ /** An immutable string. Nul terminated, but only copies in to the native function */
63
+ NATIVE_STRING,
64
+
65
+ /** The function takes a variable number of arguments */
66
+ NATIVE_VARARGS,
67
+
68
+ /** Struct-by-value param or result */
69
+ NATIVE_STRUCT,
70
+
71
+ /** An array type definition */
72
+ NATIVE_ARRAY,
73
+
74
+ /** Custom native type */
75
+ NATIVE_MAPPED,
76
+ } NativeType;
77
+
78
+ #include <ffi.h>
79
+ #include "Type.h"
80
+
81
+ VALUE rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr);
82
+ void rbffi_Types_Init(VALUE moduleFFI);
83
+
84
+ #ifdef __cplusplus
85
+ }
86
+ #endif
87
+
88
+ #endif /* RBFFI_TYPES_H */
89
+
@@ -0,0 +1,304 @@
1
+ /*
2
+ * Copyright (c) 2008-2010 Wayne Meissner
3
+ * Copyright (C) 2009 Andrea Fazzi <andrea.fazzi@alcacoop.it>
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
+ #include <sys/types.h>
34
+
35
+ #include <stdio.h>
36
+ #ifndef _MSC_VER
37
+ # include <stdint.h>
38
+ # include <stdbool.h>
39
+ #else
40
+ # include "win32/stdbool.h"
41
+ # include "win32/stdint.h"
42
+ #endif
43
+ #include <ruby.h>
44
+
45
+ #include <ffi.h>
46
+ #include "rbffi.h"
47
+ #include "compat.h"
48
+
49
+ #include "AbstractMemory.h"
50
+ #include "Pointer.h"
51
+ #include "Types.h"
52
+ #include "Type.h"
53
+ #include "LastError.h"
54
+ #include "MethodHandle.h"
55
+ #include "Call.h"
56
+ #include "Thread.h"
57
+
58
+ typedef struct VariadicInvoker_ {
59
+ VALUE rbAddress;
60
+ VALUE rbReturnType;
61
+ VALUE rbEnums;
62
+
63
+ Type* returnType;
64
+ ffi_abi abi;
65
+ void* function;
66
+ int paramCount;
67
+ bool blocking;
68
+ } VariadicInvoker;
69
+
70
+
71
+ static VALUE variadic_allocate(VALUE klass);
72
+ static VALUE variadic_initialize(VALUE self, VALUE rbFunction, VALUE rbParameterTypes,
73
+ VALUE rbReturnType, VALUE options);
74
+ static void variadic_mark(VariadicInvoker *);
75
+
76
+ static VALUE classVariadicInvoker = Qnil;
77
+
78
+
79
+ static VALUE
80
+ variadic_allocate(VALUE klass)
81
+ {
82
+ VariadicInvoker *invoker;
83
+ VALUE obj = Data_Make_Struct(klass, VariadicInvoker, variadic_mark, -1, invoker);
84
+
85
+ invoker->rbAddress = Qnil;
86
+ invoker->rbEnums = Qnil;
87
+ invoker->rbReturnType = Qnil;
88
+ invoker->blocking = false;
89
+
90
+ return obj;
91
+ }
92
+
93
+ static void
94
+ variadic_mark(VariadicInvoker *invoker)
95
+ {
96
+ rb_gc_mark(invoker->rbEnums);
97
+ rb_gc_mark(invoker->rbAddress);
98
+ rb_gc_mark(invoker->rbReturnType);
99
+ }
100
+
101
+ static VALUE
102
+ variadic_initialize(VALUE self, VALUE rbFunction, VALUE rbParameterTypes, VALUE rbReturnType, VALUE options)
103
+ {
104
+ VariadicInvoker* invoker = NULL;
105
+ VALUE retval = Qnil;
106
+ VALUE convention = Qnil;
107
+ VALUE fixed = Qnil;
108
+ #if defined(X86_WIN32)
109
+ VALUE rbConventionStr;
110
+ #endif
111
+ int i;
112
+
113
+ Check_Type(options, T_HASH);
114
+ convention = rb_hash_aref(options, ID2SYM(rb_intern("convention")));
115
+
116
+ Data_Get_Struct(self, VariadicInvoker, invoker);
117
+ invoker->rbEnums = rb_hash_aref(options, ID2SYM(rb_intern("enums")));
118
+ invoker->rbAddress = rbFunction;
119
+ invoker->function = rbffi_AbstractMemory_Cast(rbFunction, rbffi_PointerClass)->address;
120
+ invoker->blocking = RTEST(rb_hash_aref(options, ID2SYM(rb_intern("blocking"))));
121
+
122
+ #if defined(X86_WIN32)
123
+ rbConventionStr = rb_funcall2(convention, rb_intern("to_s"), 0, NULL);
124
+ invoker->abi = (RTEST(convention) && strcmp(StringValueCStr(rbConventionStr), "stdcall") == 0)
125
+ ? FFI_STDCALL : FFI_DEFAULT_ABI;
126
+ #else
127
+ invoker->abi = FFI_DEFAULT_ABI;
128
+ #endif
129
+
130
+ invoker->rbReturnType = rbffi_Type_Lookup(rbReturnType);
131
+ if (!RTEST(invoker->rbReturnType)) {
132
+ VALUE typeName = rb_funcall2(rbReturnType, rb_intern("inspect"), 0, NULL);
133
+ rb_raise(rb_eTypeError, "Invalid return type (%s)", RSTRING_PTR(typeName));
134
+ }
135
+
136
+ Data_Get_Struct(rbReturnType, Type, invoker->returnType);
137
+
138
+ invoker->paramCount = -1;
139
+
140
+ fixed = rb_ary_new2(RARRAY_LEN(rbParameterTypes) - 1);
141
+ for (i = 0; i < RARRAY_LEN(rbParameterTypes); ++i) {
142
+ VALUE entry = rb_ary_entry(rbParameterTypes, i);
143
+ VALUE rbType = rbffi_Type_Lookup(entry);
144
+ Type* type;
145
+
146
+ if (!RTEST(rbType)) {
147
+ VALUE typeName = rb_funcall2(entry, rb_intern("inspect"), 0, NULL);
148
+ rb_raise(rb_eTypeError, "Invalid parameter type (%s)", RSTRING_PTR(typeName));
149
+ }
150
+ Data_Get_Struct(rbType, Type, type);
151
+ if (type->nativeType != NATIVE_VARARGS) {
152
+ rb_ary_push(fixed, entry);
153
+ }
154
+ }
155
+ /*
156
+ * @fixed and @type_map are used by the parameter mangling ruby code
157
+ */
158
+ rb_iv_set(self, "@fixed", fixed);
159
+ rb_iv_set(self, "@type_map", rb_hash_aref(options, ID2SYM(rb_intern("type_map"))));
160
+
161
+ return retval;
162
+ }
163
+
164
+ static VALUE
165
+ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
166
+ {
167
+ VariadicInvoker* invoker;
168
+ FFIStorage* params;
169
+ void* retval;
170
+ ffi_cif cif;
171
+ void** ffiValues;
172
+ ffi_type** ffiParamTypes;
173
+ ffi_type* ffiReturnType;
174
+ Type** paramTypes;
175
+ VALUE* argv;
176
+ int paramCount = 0, fixedCount = 0, i;
177
+ ffi_status ffiStatus;
178
+ rbffi_frame_t frame = { 0 };
179
+
180
+ Check_Type(parameterTypes, T_ARRAY);
181
+ Check_Type(parameterValues, T_ARRAY);
182
+
183
+ Data_Get_Struct(self, VariadicInvoker, invoker);
184
+ paramCount = (int) RARRAY_LEN(parameterTypes);
185
+ paramTypes = ALLOCA_N(Type *, paramCount);
186
+ ffiParamTypes = ALLOCA_N(ffi_type *, paramCount);
187
+ params = ALLOCA_N(FFIStorage, paramCount);
188
+ ffiValues = ALLOCA_N(void*, paramCount);
189
+ argv = ALLOCA_N(VALUE, paramCount);
190
+ retval = alloca(MAX(invoker->returnType->ffiType->size, FFI_SIZEOF_ARG));
191
+
192
+ for (i = 0; i < paramCount; ++i) {
193
+ VALUE rbType = rb_ary_entry(parameterTypes, i);
194
+
195
+ if (!rb_obj_is_kind_of(rbType, rbffi_TypeClass)) {
196
+ rb_raise(rb_eTypeError, "wrong type. Expected (FFI::Type)");
197
+ }
198
+ Data_Get_Struct(rbType, Type, paramTypes[i]);
199
+
200
+ switch (paramTypes[i]->nativeType) {
201
+ case NATIVE_INT8:
202
+ case NATIVE_INT16:
203
+ case NATIVE_INT32:
204
+ rbType = rb_const_get(rbffi_TypeClass, rb_intern("INT32"));
205
+ Data_Get_Struct(rbType, Type, paramTypes[i]);
206
+ break;
207
+ case NATIVE_UINT8:
208
+ case NATIVE_UINT16:
209
+ case NATIVE_UINT32:
210
+ rbType = rb_const_get(rbffi_TypeClass, rb_intern("UINT32"));
211
+ Data_Get_Struct(rbType, Type, paramTypes[i]);
212
+ break;
213
+
214
+ case NATIVE_FLOAT32:
215
+ rbType = rb_const_get(rbffi_TypeClass, rb_intern("DOUBLE"));
216
+ Data_Get_Struct(rbType, Type, paramTypes[i]);
217
+ break;
218
+
219
+ default:
220
+ break;
221
+ }
222
+
223
+
224
+ ffiParamTypes[i] = paramTypes[i]->ffiType;
225
+ if (ffiParamTypes[i] == NULL) {
226
+ rb_raise(rb_eArgError, "Invalid parameter type #%x", paramTypes[i]->nativeType);
227
+ }
228
+ argv[i] = rb_ary_entry(parameterValues, i);
229
+ }
230
+
231
+ ffiReturnType = invoker->returnType->ffiType;
232
+ if (ffiReturnType == NULL) {
233
+ rb_raise(rb_eArgError, "Invalid return type");
234
+ }
235
+
236
+ /*Get the number of fixed args from @fixed array*/
237
+ fixedCount = RARRAY_LEN(rb_iv_get(self, "@fixed"));
238
+
239
+ #ifdef HAVE_FFI_PREP_CIF_VAR
240
+ ffiStatus = ffi_prep_cif_var(&cif, invoker->abi, fixedCount, paramCount, ffiReturnType, ffiParamTypes);
241
+ #else
242
+ ffiStatus = ffi_prep_cif(&cif, invoker->abi, paramCount, ffiReturnType, ffiParamTypes);
243
+ #endif
244
+ switch (ffiStatus) {
245
+ case FFI_BAD_ABI:
246
+ rb_raise(rb_eArgError, "Invalid ABI specified");
247
+ case FFI_BAD_TYPEDEF:
248
+ rb_raise(rb_eArgError, "Invalid argument type specified");
249
+ case FFI_OK:
250
+ break;
251
+ default:
252
+ rb_raise(rb_eArgError, "Unknown FFI error");
253
+ }
254
+
255
+ rbffi_SetupCallParams(paramCount, argv, -1, paramTypes, params,
256
+ ffiValues, NULL, 0, invoker->rbEnums);
257
+
258
+ rbffi_frame_push(&frame);
259
+ #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
260
+ /* In Call.c, blocking: true is supported on older ruby variants
261
+ * without rb_thread_call_without_gvl by allocating on the heap instead
262
+ * of the stack. Since this functionality is being added later,
263
+ * we’re skipping support for old rubies here. */
264
+ if(unlikely(invoker->blocking)) {
265
+ rbffi_blocking_call_t* bc;
266
+ bc = ALLOCA_N(rbffi_blocking_call_t, 1);
267
+ bc->retval = retval;
268
+ bc->function = invoker->function;
269
+ bc->ffiValues = ffiValues;
270
+ bc->params = params;
271
+ bc->frame = &frame;
272
+ bc->cif = cif;
273
+
274
+ rb_rescue2(rbffi_do_blocking_call, (VALUE) bc, rbffi_save_frame_exception, (VALUE) &frame, rb_eException, (VALUE) 0);
275
+ } else {
276
+ ffi_call(&cif, FFI_FN(invoker->function), retval, ffiValues);
277
+ }
278
+ #else
279
+ ffi_call(&cif, FFI_FN(invoker->function), retval, ffiValues);
280
+ #endif
281
+ rbffi_frame_pop(&frame);
282
+
283
+ rbffi_save_errno();
284
+
285
+ if (RTEST(frame.exc) && frame.exc != Qnil) {
286
+ rb_exc_raise(frame.exc);
287
+ }
288
+
289
+ return rbffi_NativeValue_ToRuby(invoker->returnType, invoker->rbReturnType, retval);
290
+ }
291
+
292
+
293
+ void
294
+ rbffi_Variadic_Init(VALUE moduleFFI)
295
+ {
296
+ classVariadicInvoker = rb_define_class_under(moduleFFI, "VariadicInvoker", rb_cObject);
297
+ rb_global_variable(&classVariadicInvoker);
298
+
299
+ rb_define_alloc_func(classVariadicInvoker, variadic_allocate);
300
+
301
+ rb_define_method(classVariadicInvoker, "initialize", variadic_initialize, 4);
302
+ rb_define_method(classVariadicInvoker, "invoke", variadic_invoke, 2);
303
+ }
304
+