ffi 0.6.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

Files changed (92) hide show
  1. data/History.txt +7 -0
  2. data/LICENSE +10 -21
  3. data/README.rdoc +70 -0
  4. data/Rakefile +56 -84
  5. data/ext/ffi_c/AbstractMemory.c +56 -38
  6. data/ext/ffi_c/AbstractMemory.h +15 -22
  7. data/ext/ffi_c/Buffer.c +61 -22
  8. data/ext/ffi_c/Call.c +52 -540
  9. data/ext/ffi_c/Call.h +1 -1
  10. data/ext/ffi_c/DataConverter.c +62 -0
  11. data/ext/ffi_c/DynamicLibrary.c +21 -1
  12. data/ext/ffi_c/Function.c +252 -30
  13. data/ext/ffi_c/MappedType.c +146 -0
  14. data/{libtest/FunctionTest.c → ext/ffi_c/MappedType.h} +32 -25
  15. data/ext/ffi_c/MemoryPointer.c +12 -33
  16. data/ext/ffi_c/Platform.c +2 -0
  17. data/ext/ffi_c/Pointer.c +66 -28
  18. data/ext/ffi_c/Struct.c +19 -306
  19. data/ext/ffi_c/Struct.h +6 -0
  20. data/ext/ffi_c/StructByReference.c +150 -0
  21. data/{libtest/LastErrorTest.c → ext/ffi_c/StructByReference.h} +30 -21
  22. data/ext/ffi_c/StructLayout.c +26 -16
  23. data/ext/ffi_c/Type.c +39 -68
  24. data/ext/ffi_c/Type.h +12 -22
  25. data/ext/ffi_c/Types.c +20 -5
  26. data/ext/ffi_c/Types.h +7 -7
  27. data/ext/ffi_c/Variadic.c +21 -17
  28. data/ext/ffi_c/extconf.rb +4 -0
  29. data/ext/ffi_c/ffi.c +8 -2
  30. data/ext/ffi_c/rbffi.h +1 -0
  31. data/lib/ffi/autopointer.rb +23 -22
  32. data/lib/ffi/enum.rb +36 -21
  33. data/lib/ffi/errno.rb +20 -0
  34. data/lib/ffi/ffi.rb +13 -80
  35. data/lib/ffi/io.rb +12 -20
  36. data/lib/ffi/library.rb +109 -92
  37. data/lib/ffi/managedstruct.rb +1 -1
  38. data/lib/ffi/memorypointer.rb +15 -21
  39. data/lib/ffi/platform.rb +27 -33
  40. data/lib/ffi/pointer.rb +14 -21
  41. data/lib/ffi/struct.rb +98 -49
  42. data/lib/ffi/struct_layout_builder.rb +158 -0
  43. data/lib/ffi/types.rb +99 -128
  44. data/lib/ffi/union.rb +20 -0
  45. data/lib/ffi/variadic.rb +33 -22
  46. data/spec/ffi/async_callback_spec.rb +23 -0
  47. data/spec/ffi/callback_spec.rb +62 -0
  48. data/spec/ffi/custom_param_type.rb +31 -0
  49. data/spec/ffi/custom_type_spec.rb +73 -0
  50. data/spec/ffi/enum_spec.rb +19 -0
  51. data/spec/ffi/ffi_spec.rb +24 -0
  52. data/spec/ffi/pointer_spec.rb +15 -0
  53. data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
  54. data/spec/ffi/strptr_spec.rb +36 -0
  55. data/spec/ffi/struct_packed_spec.rb +46 -0
  56. data/spec/ffi/struct_spec.rb +19 -5
  57. data/spec/ffi/typedef_spec.rb +14 -0
  58. data/tasks/ann.rake +80 -0
  59. data/tasks/extension.rake +25 -0
  60. data/tasks/gem.rake +200 -0
  61. data/tasks/git.rake +41 -0
  62. data/tasks/notes.rake +27 -0
  63. data/tasks/post_load.rake +34 -0
  64. data/tasks/rdoc.rake +50 -0
  65. data/tasks/rubyforge.rake +55 -0
  66. data/tasks/setup.rb +301 -0
  67. data/tasks/spec.rake +54 -0
  68. data/tasks/svn.rake +47 -0
  69. data/tasks/test.rake +40 -0
  70. metadata +139 -131
  71. data/README.md +0 -109
  72. data/ext/ffi_c/AutoPointer.c +0 -60
  73. data/ext/ffi_c/AutoPointer.h +0 -18
  74. data/ext/ffi_c/Ffi_c.iml +0 -12
  75. data/ffi.gemspec +0 -18
  76. data/gen/log +0 -1
  77. data/lib/Lib.iml +0 -21
  78. data/libtest/Benchmark.c +0 -73
  79. data/libtest/BoolTest.c +0 -52
  80. data/libtest/BufferTest.c +0 -52
  81. data/libtest/ClosureTest.c +0 -173
  82. data/libtest/EnumTest.c +0 -55
  83. data/libtest/GNUmakefile +0 -141
  84. data/libtest/GlobalVariable.c +0 -56
  85. data/libtest/NumberTest.c +0 -145
  86. data/libtest/PointerTest.c +0 -84
  87. data/libtest/ReferenceTest.c +0 -44
  88. data/libtest/StringTest.c +0 -55
  89. data/libtest/StructTest.c +0 -247
  90. data/libtest/UnionTest.c +0 -64
  91. data/libtest/VariadicTest.c +0 -57
  92. data/spec/ffi/Ffi.iml +0 -12
@@ -3,27 +3,19 @@
3
3
  *
4
4
  * All rights reserved.
5
5
  *
6
- * Redistribution and use in source and binary forms, with or without
7
- * modification, are permitted provided that the following conditions are met:
6
+ * This file is part of ruby-ffi.
8
7
  *
9
- * * Redistributions of source code must retain the above copyright notice, this
10
- * list of conditions and the following disclaimer.
11
- * * Redistributions in binary form must reproduce the above copyright notice
12
- * this list of conditions and the following disclaimer in the documentation
13
- * and/or other materials provided with the distribution.
14
- * * The name of the author or authors may not be used to endorse or promote
15
- * products derived from this software without specific prior written permission.
8
+ * This code is free software: you can redistribute it and/or modify it under
9
+ * the terms of the GNU Lesser General Public License version 3 only, as
10
+ * published by the Free Software Foundation.
16
11
  *
17
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12
+ * This code is distributed in the hope that it will be useful, but WITHOUT
13
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15
+ * version 3 for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public License
18
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
27
19
  */
28
20
 
29
21
  #ifndef RBFFI_ABSTRACTMEMORY_H
@@ -44,6 +36,7 @@ extern "C" {
44
36
  #define MEM_RD 0x01
45
37
  #define MEM_WR 0x02
46
38
  #define MEM_CODE 0x04
39
+ #define MEM_SWAP 0x08
47
40
 
48
41
  typedef struct AbstractMemory_ AbstractMemory;
49
42
 
@@ -72,7 +65,7 @@ typedef struct {
72
65
  struct AbstractMemory_ {
73
66
  char* address; // Use char* instead of void* to ensure adding to it works correctly
74
67
  long size;
75
- int access;
68
+ int flags;
76
69
  int typeSize;
77
70
  };
78
71
 
@@ -98,7 +91,7 @@ checkBounds(AbstractMemory* mem, long off, long len)
98
91
  static inline void
99
92
  checkRead(AbstractMemory* mem)
100
93
  {
101
- if (unlikely((mem->access & MEM_RD) == 0)) {
94
+ if (unlikely((mem->flags & MEM_RD) == 0)) {
102
95
  rbffi_AbstractMemory_Error(mem, MEM_RD);
103
96
  }
104
97
  }
@@ -106,7 +99,7 @@ checkRead(AbstractMemory* mem)
106
99
  static inline void
107
100
  checkWrite(AbstractMemory* mem)
108
101
  {
109
- if (unlikely((mem->access & MEM_WR) == 0)) {
102
+ if (unlikely((mem->flags & MEM_WR) == 0)) {
110
103
  rbffi_AbstractMemory_Error(mem, MEM_WR);
111
104
  }
112
105
  }
data/ext/ffi_c/Buffer.c CHANGED
@@ -1,28 +1,21 @@
1
1
  /*
2
- * Copyright (c) 2008, 2009, Wayne Meissner
2
+ * Copyright (c) 2008-2010 Wayne Meissner
3
+ *
3
4
  * All rights reserved.
4
5
  *
5
- * Redistribution and use in source and binary forms, with or without
6
- * modification, are permitted provided that the following conditions are met:
6
+ * This file is part of ruby-ffi.
7
7
  *
8
- * * Redistributions of source code must retain the above copyright notice, this
9
- * list of conditions and the following disclaimer.
10
- * * Redistributions in binary form must reproduce the above copyright notice
11
- * this list of conditions and the following disclaimer in the documentation
12
- * and/or other materials provided with the distribution.
13
- * * The name of the author or authors may not be used to endorse or promote
14
- * products derived from this software without specific prior written permission.
8
+ * This code is free software: you can redistribute it and/or modify it under
9
+ * the terms of the GNU Lesser General Public License version 3 only, as
10
+ * published by the Free Software Foundation.
15
11
  *
16
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12
+ * This code is distributed in the hope that it will be useful, but WITHOUT
13
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15
+ * version 3 for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public License
18
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
26
19
  */
27
20
 
28
21
  #include <stdbool.h>
@@ -54,7 +47,7 @@ buffer_allocate(VALUE klass)
54
47
 
55
48
  obj = Data_Make_Struct(klass, Buffer, NULL, buffer_release, buffer);
56
49
  buffer->rbParent = Qnil;
57
- buffer->memory.access = MEM_RD | MEM_WR;
50
+ buffer->memory.flags = MEM_RD | MEM_WR;
58
51
 
59
52
  return obj;
60
53
  }
@@ -122,7 +115,7 @@ slice(VALUE self, long offset, long len)
122
115
  obj = Data_Make_Struct(BufferClass, Buffer, buffer_mark, -1, result);
123
116
  result->memory.address = ptr->memory.address + offset;
124
117
  result->memory.size = len;
125
- result->memory.access = ptr->memory.access;
118
+ result->memory.flags = ptr->memory.flags;
126
119
  result->memory.typeSize = ptr->memory.typeSize;
127
120
  result->rbParent = self;
128
121
 
@@ -159,6 +152,51 @@ buffer_inspect(VALUE self)
159
152
  return rb_str_new2(tmp);
160
153
  }
161
154
 
155
+
156
+ #if BYTE_ORDER == LITTLE_ENDIAN
157
+ # define SWAPPED_ORDER BIG_ENDIAN
158
+ #else
159
+ # define SWAPPED_ORDER LITTLE_ENDIAN
160
+ #endif
161
+
162
+ static VALUE
163
+ buffer_order(int argc, VALUE* argv, VALUE self)
164
+ {
165
+ Buffer* ptr;
166
+
167
+ Data_Get_Struct(self, Buffer, ptr);
168
+ if (argc == 0) {
169
+ int order = (ptr->memory.flags & MEM_SWAP) == 0 ? BYTE_ORDER : SWAPPED_ORDER;
170
+ return order == BIG_ENDIAN ? ID2SYM(rb_intern("big")) : ID2SYM(rb_intern("little"));
171
+ } else {
172
+ VALUE rbOrder = Qnil;
173
+ int order = BYTE_ORDER;
174
+
175
+ if (rb_scan_args(argc, argv, "1", &rbOrder) < 1) {
176
+ rb_raise(rb_eArgError, "need byte order");
177
+ }
178
+ if (SYMBOL_P(rbOrder)) {
179
+ ID id = SYM2ID(rbOrder);
180
+ if (id == rb_intern("little")) {
181
+ order = LITTLE_ENDIAN;
182
+
183
+ } else if (id == rb_intern("big") || id == rb_intern("network")) {
184
+ order = BIG_ENDIAN;
185
+ }
186
+ }
187
+ if (order != BYTE_ORDER) {
188
+ Buffer* p2;
189
+ VALUE retval = slice(self, 0, ptr->memory.size);
190
+
191
+ Data_Get_Struct(retval, Buffer, p2);
192
+ p2->memory.flags |= MEM_SWAP;
193
+ return retval;
194
+ }
195
+
196
+ return self;
197
+ }
198
+ }
199
+
162
200
  /* Only used to free the buffer if the yield in the initializer throws an exception */
163
201
  static VALUE
164
202
  buffer_free(VALUE self)
@@ -196,6 +234,7 @@ rbffi_Buffer_Init(VALUE moduleFFI)
196
234
  rb_define_alias(rb_singleton_class(BufferClass), "new_inout", "alloc_inout");
197
235
 
198
236
  rb_define_method(BufferClass, "initialize", buffer_initialize, -1);
237
+ rb_define_method(BufferClass, "order", buffer_order, -1);
199
238
  rb_define_method(BufferClass, "inspect", buffer_inspect, 0);
200
239
  rb_define_alias(BufferClass, "length", "total");
201
240
  rb_define_method(BufferClass, "+", buffer_plus, 1);
data/ext/ffi_c/Call.c CHANGED
@@ -5,27 +5,19 @@
5
5
  * Copyright (c) 2009, Aman Gupta.
6
6
  * All rights reserved.
7
7
  *
8
- * Redistribution and use in source and binary forms, with or without
9
- * modification, are permitted provided that the following conditions are met:
8
+ * This file is part of ruby-ffi.
10
9
  *
11
- * * Redistributions of source code must retain the above copyright notice, this
12
- * list of conditions and the following disclaimer.
13
- * * Redistributions in binary form must reproduce the above copyright notice
14
- * this list of conditions and the following disclaimer in the documentation
15
- * and/or other materials provided with the distribution.
16
- * * The name of the author or authors may not be used to endorse or promote
17
- * products derived from this software without specific prior written permission.
10
+ * This code is free software: you can redistribute it and/or modify it under
11
+ * the terms of the GNU Lesser General Public License version 3 only, as
12
+ * published by the Free Software Foundation.
18
13
  *
19
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
+ * This code is distributed in the hope that it will be useful, but WITHOUT
15
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
17
+ * version 3 for more details.
18
+ *
19
+ * You should have received a copy of the GNU Lesser General Public License
20
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
29
21
  */
30
22
 
31
23
  #include <sys/param.h>
@@ -50,6 +42,7 @@
50
42
  #include "Type.h"
51
43
  #include "LastError.h"
52
44
  #include "Call.h"
45
+ #include "MappedType.h"
53
46
 
54
47
  #ifdef USE_RAW
55
48
  # ifndef __i386__
@@ -74,30 +67,13 @@
74
67
  #endif
75
68
 
76
69
  static void* callback_param(VALUE proc, VALUE cbinfo);
77
- static inline int getSignedInt(VALUE value, int type, int minValue, int maxValue, const char* typeName, VALUE enums);
78
- static inline int getUnsignedInt(VALUE value, int type, int maxValue, const char* typeName);
79
- static inline unsigned int getUnsignedInt32(VALUE value, int type);
80
70
  static inline void* getPointer(VALUE value, int type);
81
71
  static inline char* getString(VALUE value, int type);
82
72
 
83
-
84
- #ifdef BYPASS_FFI
85
- static long rbffi_GetLongValue(int idx, VALUE* argv, FunctionType* fnInfo);
86
- static VALUE rbffi_InvokeVrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
87
- static VALUE rbffi_InvokeLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
88
- static VALUE rbffi_InvokeLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
89
- static VALUE rbffi_InvokeLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
90
- static VALUE rbffi_InvokeLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
91
- static VALUE rbffi_InvokeLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
92
- static VALUE rbffi_InvokeLLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
93
- static VALUE rbffi_InvokeLongParams(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
94
- #endif
95
-
96
-
97
- static ID id_to_ptr, id_map_symbol;
73
+ static ID id_to_ptr, id_map_symbol, id_to_native;
98
74
 
99
75
  void
100
- rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTypes,
76
+ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
101
77
  FFIStorage* paramStorage, void** ffiValues,
102
78
  VALUE* callbackParameters, int callbackCount, VALUE enums)
103
79
  {
@@ -105,7 +81,7 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy
105
81
  FFIStorage* param = &paramStorage[0];
106
82
  int i, argidx, cbidx, argCount;
107
83
 
108
- if (paramCount != -1 && paramCount != argc) {
84
+ if (unlikely(paramCount != -1 && paramCount != argc)) {
109
85
  if (argc == (paramCount - 1) && callbackCount == 1 && rb_block_given_p()) {
110
86
  callbackProc = rb_block_proc();
111
87
  } else {
@@ -116,26 +92,45 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy
116
92
  argCount = paramCount != -1 ? paramCount : argc;
117
93
 
118
94
  for (i = 0, argidx = 0, cbidx = 0; i < argCount; ++i) {
119
- int type = argidx < argc ? TYPE(argv[argidx]) : T_NONE;
95
+ Type* paramType = paramTypes[i];
96
+ int type;
97
+
98
+
99
+ if (unlikely(paramType->nativeType == NATIVE_MAPPED)) {
100
+ VALUE values[] = { argv[argidx], Qnil };
101
+ argv[argidx] = rb_funcall2(((MappedType *) paramType)->rbConverter, id_to_native, 2, values);
102
+ paramType = ((MappedType *) paramType)->type;
103
+ }
104
+
105
+ type = argidx < argc ? TYPE(argv[argidx]) : T_NONE;
120
106
  ffiValues[i] = param;
121
107
 
122
- switch (paramTypes[i]) {
108
+ switch (paramType->nativeType) {
123
109
 
124
110
  case NATIVE_INT8:
125
- param->s8 = getSignedInt(argv[argidx++], type, -128, 127, "char", Qnil);
111
+ param->s8 = NUM2INT(argv[argidx]);
112
+ ++argidx;
126
113
  ADJ(param, INT8);
127
114
  break;
128
115
 
129
116
 
130
117
  case NATIVE_INT16:
131
- param->s16 = getSignedInt(argv[argidx++], type, -0x8000, 0x7fff, "short", Qnil);
118
+ param->s16 = NUM2INT(argv[argidx]);
119
+ ++argidx;
132
120
  ADJ(param, INT16);
133
121
  break;
134
122
 
135
123
 
136
124
  case NATIVE_INT32:
137
- case NATIVE_ENUM:
138
- param->s32 = getSignedInt(argv[argidx++], type, -0x80000000, 0x7fffffff, "int", enums);
125
+ if (unlikely(type == T_SYMBOL && enums != Qnil)) {
126
+ VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]);
127
+ param->s32 = NUM2INT(value);
128
+
129
+ } else {
130
+ param->s32 = NUM2INT(argv[argidx]);
131
+ }
132
+
133
+ ++argidx;
139
134
  ADJ(param, INT32);
140
135
  break;
141
136
 
@@ -150,28 +145,27 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy
150
145
 
151
146
 
152
147
  case NATIVE_UINT8:
153
- param->u8 = getUnsignedInt(argv[argidx++], type, 0xff, "unsigned char");
148
+ param->u8 = NUM2UINT(argv[argidx]);
154
149
  ADJ(param, INT8);
150
+ ++argidx;
155
151
  break;
156
152
 
157
153
 
158
154
  case NATIVE_UINT16:
159
- param->u16 = getUnsignedInt(argv[argidx++], type, 0xffff, "unsigned short");
155
+ param->u16 = NUM2UINT(argv[argidx]);
160
156
  ADJ(param, INT16);
157
+ ++argidx;
161
158
  break;
162
159
 
163
160
 
164
161
  case NATIVE_UINT32:
165
- /* Special handling/checking for unsigned 32 bit integers */
166
- param->u32 = getUnsignedInt32(argv[argidx++], type);
162
+ param->u32 = NUM2UINT(argv[argidx]);
167
163
  ADJ(param, INT32);
164
+ ++argidx;
168
165
  break;
169
166
 
170
167
 
171
168
  case NATIVE_INT64:
172
- if (type != T_FIXNUM && type != T_BIGNUM) {
173
- rb_raise(rb_eTypeError, "Expected an Integer parameter");
174
- }
175
169
  param->i64 = NUM2LL(argv[argidx]);
176
170
  ADJ(param, INT64);
177
171
  ++argidx;
@@ -179,9 +173,6 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy
179
173
 
180
174
 
181
175
  case NATIVE_UINT64:
182
- if (type != T_FIXNUM && type != T_BIGNUM) {
183
- rb_raise(rb_eTypeError, "Expected an Integer parameter");
184
- }
185
176
  param->u64 = NUM2ULL(argv[argidx]);
186
177
  ADJ(param, INT64);
187
178
  ++argidx;
@@ -200,18 +191,12 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy
200
191
  break;
201
192
 
202
193
  case NATIVE_FLOAT32:
203
- if (type != T_FLOAT && type != T_FIXNUM) {
204
- rb_raise(rb_eTypeError, "Expected a Float parameter");
205
- }
206
194
  param->f32 = (float) NUM2DBL(argv[argidx]);
207
195
  ADJ(param, FLOAT32);
208
196
  ++argidx;
209
197
  break;
210
198
 
211
199
  case NATIVE_FLOAT64:
212
- if (type != T_FLOAT && type != T_FIXNUM) {
213
- rb_raise(rb_eTypeError, "Expected a Float parameter");
214
- }
215
200
  param->f64 = NUM2DBL(argv[argidx]);
216
201
  ADJ(param, FLOAT64);
217
202
  ++argidx;
@@ -248,7 +233,7 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy
248
233
  break;
249
234
 
250
235
  default:
251
- rb_raise(rb_eArgError, "Invalid parameter type: %d", paramTypes[i]);
236
+ rb_raise(rb_eArgError, "Invalid parameter type: %d", paramType->nativeType);
252
237
  }
253
238
  }
254
239
  }
@@ -286,7 +271,7 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
286
271
  retval = alloca(MAX(fnInfo->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
287
272
 
288
273
  rbffi_SetupCallParams(argc, argv,
289
- fnInfo->parameterCount, fnInfo->nativeParameterTypes, params, ffiValues,
274
+ fnInfo->parameterCount, fnInfo->parameterTypes, params, ffiValues,
290
275
  fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
291
276
 
292
277
  #if defined(HAVE_NATIVETHREAD) && defined(HAVE_RB_THREAD_BLOCKING_REGION)
@@ -306,7 +291,7 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
306
291
  ffi_call(&fnInfo->ffi_cif, FFI_FN(function), retval, ffiValues);
307
292
  #endif
308
293
 
309
- if (!fnInfo->ignoreErrno) {
294
+ if (unlikely(!fnInfo->ignoreErrno)) {
310
295
  rbffi_save_errno();
311
296
  }
312
297
 
@@ -314,68 +299,10 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
314
299
  fnInfo->rbEnums);
315
300
  }
316
301
 
317
- static inline int
318
- getSignedInt(VALUE value, int type, int minValue, int maxValue, const char* typeName, VALUE enums)
319
- {
320
- int i;
321
-
322
- if (type == T_SYMBOL && enums != Qnil) {
323
- value = rb_funcall2(enums, id_map_symbol, 1, &value);
324
- if (value == Qnil) {
325
- rb_raise(rb_eTypeError, "Expected a valid enum constant");
326
- }
327
-
328
- } else if (type != T_FIXNUM && type != T_BIGNUM) {
329
- rb_raise(rb_eTypeError, "Expected an Integer parameter");
330
- }
331
-
332
- i = NUM2INT(value);
333
- if (i < minValue || i > maxValue) {
334
- rb_raise(rb_eRangeError, "Value %d outside %s range", i, typeName);
335
- }
336
-
337
- return i;
338
- }
339
-
340
- static inline int
341
- getUnsignedInt(VALUE value, int type, int maxValue, const char* typeName)
342
- {
343
- int i;
344
-
345
- if (type != T_FIXNUM && type != T_BIGNUM) {
346
- rb_raise(rb_eTypeError, "Expected an Integer parameter");
347
- }
348
-
349
- i = NUM2INT(value);
350
- if (i < 0 || i > maxValue) {
351
- rb_raise(rb_eRangeError, "Value %d outside %s range", i, typeName);
352
- }
353
-
354
- return i;
355
- }
356
-
357
- /* Special handling/checking for unsigned 32 bit integers */
358
- static inline unsigned int
359
- getUnsignedInt32(VALUE value, int type)
360
- {
361
- long long i;
362
-
363
- if (type != T_FIXNUM && type != T_BIGNUM) {
364
- rb_raise(rb_eTypeError, "Expected an Integer parameter");
365
- }
366
-
367
- i = NUM2LL(value);
368
- if (i < 0L || i > 0xffffffffL) {
369
- rb_raise(rb_eRangeError, "Value %lld outside unsigned int range", i);
370
- }
371
-
372
- return (unsigned int) i;
373
- }
374
-
375
302
  static inline void*
376
303
  getPointer(VALUE value, int type)
377
304
  {
378
- if (type == T_DATA && rb_obj_is_kind_of(value, rbffi_AbstractMemoryClass)) {
305
+ if (likely(type == T_DATA && rb_obj_is_kind_of(value, rbffi_AbstractMemoryClass))) {
379
306
 
380
307
  return ((AbstractMemory *) DATA_PTR(value))->address;
381
308
 
@@ -430,431 +357,15 @@ getString(VALUE value, int type)
430
357
  Invoker
431
358
  rbffi_GetInvoker(FunctionType *fnInfo)
432
359
  {
433
- #if defined(BYPASS_FFI) && (defined(__i386__) || defined(__x86_64__))
434
- int i;
435
- bool fastLong = fnInfo->abi == FFI_DEFAULT_ABI && !fnInfo->blocking && !fnInfo->hasStruct;
436
-
437
- switch (fnInfo->returnType->nativeType) {
438
- case NATIVE_VOID:
439
- case NATIVE_BOOL:
440
- case NATIVE_INT8:
441
- case NATIVE_UINT8:
442
- case NATIVE_INT16:
443
- case NATIVE_UINT16:
444
- case NATIVE_INT32:
445
- case NATIVE_UINT32:
446
- case NATIVE_LONG:
447
- case NATIVE_ULONG:
448
- #ifdef __x86_64__
449
- case NATIVE_INT64:
450
- case NATIVE_UINT64:
451
- #endif
452
- case NATIVE_STRING:
453
- case NATIVE_POINTER:
454
- break;
455
- default:
456
- fastLong = false;
457
- break;
458
- }
459
-
460
- for (i = 0; fastLong && i < fnInfo->parameterCount; ++i) {
461
- switch (fnInfo->nativeParameterTypes[i]) {
462
- case NATIVE_BOOL:
463
- case NATIVE_INT8:
464
- case NATIVE_UINT8:
465
- case NATIVE_INT16:
466
- case NATIVE_UINT16:
467
- case NATIVE_INT32:
468
- case NATIVE_UINT32:
469
- case NATIVE_LONG:
470
- case NATIVE_ULONG:
471
- #ifdef __x86_64__
472
- case NATIVE_INT64:
473
- case NATIVE_UINT64:
474
- #endif
475
- case NATIVE_STRING:
476
- case NATIVE_POINTER:
477
- case NATIVE_BUFFER_IN:
478
- case NATIVE_BUFFER_OUT:
479
- case NATIVE_BUFFER_INOUT:
480
- case NATIVE_FUNCTION:
481
- case NATIVE_CALLBACK:
482
- break;
483
- default:
484
- fastLong = false;
485
- break;
486
- }
487
- }
488
-
489
- if (fastLong && fnInfo->callbackCount < 1) {
490
- switch (fnInfo->parameterCount) {
491
- case 0:
492
- return rbffi_InvokeVrL;
493
- case 1:
494
- return rbffi_InvokeLrL;
495
- case 2:
496
- return rbffi_InvokeLLrL;
497
- case 3:
498
- return rbffi_InvokeLLLrL;
499
- case 4:
500
- return rbffi_InvokeLLLLrL;
501
- case 5:
502
- return rbffi_InvokeLLLLLrL;
503
- case 6:
504
- return rbffi_InvokeLLLLLLrL;
505
-
506
- default:
507
- break;
508
- }
509
-
510
- } else if (fastLong && fnInfo->parameterCount <= 6) {
511
- return rbffi_InvokeLongParams;
512
- }
513
- #endif
514
-
515
360
  return rbffi_CallFunction;
516
361
  }
517
362
 
518
- #if defined(BYPASS_FFI) && (defined(__i386__) || defined(__x86_64__))
519
- typedef long L;
520
-
521
- static long
522
- rbffi_GetLongValue(int idx, VALUE* argv, FunctionType* fnInfo)
523
- {
524
- VALUE value = argv[idx];
525
- NativeType nativeType = fnInfo->nativeParameterTypes[idx];
526
- int type = TYPE(value);
527
-
528
- switch (nativeType) {
529
- case NATIVE_INT8:
530
- return getSignedInt(value, type, -128, 127, "char", fnInfo->rbEnums);
531
-
532
- case NATIVE_INT16:
533
- return getSignedInt(value, type, -0x8000, 0x7fff, "short", fnInfo->rbEnums);
534
-
535
- case NATIVE_INT32:
536
- case NATIVE_ENUM:
537
- return getSignedInt(value, type, -0x80000000, 0x7fffffff, "int", fnInfo->rbEnums);
538
-
539
- case NATIVE_BOOL:
540
- if (type != T_TRUE && type != T_FALSE) {
541
- rb_raise(rb_eTypeError, "Expected a Boolean parameter");
542
- }
543
- return RTEST(value) ? 1 : 0;
544
-
545
- case NATIVE_UINT8:
546
- return getUnsignedInt(value, type, 0xff, "unsigned char");
547
-
548
- case NATIVE_UINT16:
549
- return getUnsignedInt(value, type, 0xffff, "unsigned short");
550
-
551
- case NATIVE_UINT32:
552
- /* Special handling/checking for unsigned 32 bit integers */
553
- return getUnsignedInt32(value, type);
554
-
555
- case NATIVE_LONG:
556
- return NUM2LONG(value);
557
-
558
- case NATIVE_ULONG:
559
- return NUM2ULONG(value);
560
-
561
- #ifdef __x86_64__
562
- case NATIVE_INT64:
563
- if (type != T_FIXNUM && type != T_BIGNUM) {
564
- rb_raise(rb_eTypeError, "Expected an Integer parameter");
565
- }
566
- return NUM2LL(value);
567
-
568
- case NATIVE_UINT64:
569
- if (type != T_FIXNUM && type != T_BIGNUM) {
570
- rb_raise(rb_eTypeError, "Expected an Integer parameter");
571
- }
572
- return NUM2ULL(value);
573
- #endif
574
- case NATIVE_STRING:
575
- return (intptr_t) getString(value, type);
576
-
577
- case NATIVE_POINTER:
578
- case NATIVE_BUFFER_IN:
579
- case NATIVE_BUFFER_OUT:
580
- case NATIVE_BUFFER_INOUT:
581
- return (intptr_t) getPointer(value, type);
582
-
583
- default:
584
- rb_raise(rb_eTypeError, "unsupported integer type %d", nativeType);
585
- return 0;
586
- }
587
- }
588
-
589
- static inline void
590
- checkArity(int argc, int arity) {
591
- if (unlikely(argc != arity)) {
592
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, arity);
593
- }
594
- }
595
-
596
- static inline bool
597
- isLongValue(VALUE value)
598
- {
599
- int type = TYPE(value);
600
-
601
- return type == T_FIXNUM || type == T_BIGNUM
602
- || type == T_STRING || type == T_NIL
603
- || (type == T_DATA && rb_obj_is_kind_of(value, rbffi_AbstractMemoryClass))
604
- || (type == T_DATA && rb_obj_is_kind_of(value, rbffi_StructClass))
605
- || rb_respond_to(value, id_to_ptr);
606
- }
607
-
608
- static VALUE
609
- returnL(FunctionType* fnInfo, L* result)
610
- {
611
- if (unlikely(!fnInfo->ignoreErrno)) {
612
- rbffi_save_errno();
613
- }
614
-
615
- /*
616
- * This needs to do custom boxing of the return value, since a function
617
- * may only fill out the lower 8, 16 or 32 bits of %al, %ah, %eax, %rax, and
618
- * the upper part will be garbage. This will truncate the value again, then
619
- * sign extend it.
620
- */
621
- switch (fnInfo->returnType->nativeType) {
622
- case NATIVE_VOID:
623
- return Qnil;
624
-
625
- case NATIVE_INT8:
626
- return INT2NUM(*(signed char *) result);
627
-
628
- case NATIVE_INT16:
629
- return INT2NUM(*(signed short *) result);
630
-
631
- case NATIVE_INT32:
632
- return INT2NUM(*(signed int *) result);
633
-
634
- case NATIVE_LONG:
635
- return LONG2NUM(*(signed long *) result);
636
-
637
- case NATIVE_UINT8:
638
- return UINT2NUM(*(unsigned char *) result);
639
-
640
- case NATIVE_UINT16:
641
- return UINT2NUM(*(unsigned short *) result);
642
-
643
- case NATIVE_UINT32:
644
- return UINT2NUM(*(unsigned int *) result);
645
-
646
- case NATIVE_ULONG:
647
- return ULONG2NUM(*(unsigned long *) result);
648
-
649
- #ifdef __x86_64__
650
- case NATIVE_INT64:
651
- return LL2NUM(*(signed long long *) result);
652
-
653
- case NATIVE_UINT64:
654
- return ULL2NUM(*(unsigned long long *) result);
655
- #endif /* __x86_64__ */
656
-
657
- case NATIVE_STRING:
658
- return *(void **) result != 0 ? rb_tainted_str_new2(*(char **) result) : Qnil;
659
-
660
- case NATIVE_POINTER:
661
- return rbffi_Pointer_NewInstance(*(void **) result);
662
-
663
- case NATIVE_BOOL:
664
- return *(char *) result != 0 ? Qtrue : Qfalse;
665
-
666
- default:
667
- rb_raise(rb_eRuntimeError, "invalid return type: %d", fnInfo->returnType->nativeType);
668
- return Qnil;
669
- }
670
- }
671
-
672
- static VALUE
673
- rbffi_InvokeVrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
674
- {
675
- L (*fn)(void) = (L (*)(void)) function;
676
- L result;
677
-
678
- checkArity(argc, 0);
679
-
680
- result = (*fn)();
681
-
682
- return returnL(fnInfo, &result);
683
- }
684
-
685
- static bool
686
- checkArgs(int argc, VALUE* argv, FunctionType* fnInfo)
687
- {
688
- int i;
689
-
690
- checkArity(argc, fnInfo->parameterCount);
691
- for (i = 0; i < fnInfo->parameterCount; ++i) {
692
- if (unlikely(!isLongValue(argv[i]))) {
693
- return false;
694
- }
695
- }
696
-
697
- return true;
698
- }
699
-
700
- #define LARG(fnInfo, argv, i) \
701
- rbffi_GetLongValue(i, argv, fnInfo)
702
-
703
- #define LCALL(fnInfo, argc, argv, fn, a...) ({ \
704
- L result; \
705
- \
706
- if (unlikely(!checkArgs(argc, argv, fnInfo))) { \
707
- return rbffi_CallFunction(argc, argv, function, fnInfo); \
708
- } \
709
- \
710
- result = (*(fn))(a); \
711
- \
712
- returnL(fnInfo, &result); \
713
- })
714
-
715
- static VALUE
716
- rbffi_InvokeLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
717
- {
718
- L (*fn)(L) = (L (*)(L)) function;
719
- L result;
720
-
721
- checkArity(argc, 1);
722
-
723
- if (unlikely(!isLongValue(argv[0]))) {
724
- return rbffi_CallFunction(argc, argv, function, fnInfo);
725
- }
726
-
727
- result = (*fn)(LARG(fnInfo, argv, 0));
728
-
729
- return returnL(fnInfo, &result);
730
- }
731
-
732
- static VALUE
733
- rbffi_InvokeLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
734
- {
735
- L (*fn)(L, L) = (L (*)(L, L)) function;
736
- L result;
737
-
738
- checkArity(argc, 2);
739
-
740
- if (unlikely(!isLongValue(argv[0])) || unlikely(!isLongValue(argv[1]))) {
741
- return rbffi_CallFunction(argc, argv, function, fnInfo);
742
- }
743
-
744
- result = (*fn)(LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1));
745
-
746
- return returnL(fnInfo, &result);
747
- }
748
-
749
- static VALUE
750
- rbffi_InvokeLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
751
- {
752
- L (*fn)(L, L, L) = (L (*)(L, L, L)) function;
753
- L result;
754
-
755
- checkArity(argc, 3);
756
-
757
- if (unlikely(!isLongValue(argv[0])) || unlikely(!isLongValue(argv[1])) || unlikely(!isLongValue(argv[2]))) {
758
- return rbffi_CallFunction(argc, argv, function, fnInfo);
759
- }
760
-
761
- result = (*fn)(LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1), LARG(fnInfo, argv, 2));
762
-
763
- return returnL(fnInfo, &result);
764
- }
765
-
766
-
767
- static VALUE
768
- rbffi_InvokeLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
769
- {
770
- return LCALL(fnInfo, argc, argv, (L (*)(L, L, L, L)) function,
771
- LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1),
772
- LARG(fnInfo, argv, 2), LARG(fnInfo, argv, 3));
773
- }
774
-
775
- static VALUE
776
- rbffi_InvokeLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
777
- {
778
- return LCALL(fnInfo, argc, argv, (L (*)(L, L, L, L, L)) function,
779
- LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1), LARG(fnInfo, argv, 2),
780
- LARG(fnInfo, argv, 3), LARG(fnInfo, argv, 4));
781
- }
782
-
783
- static VALUE
784
- rbffi_InvokeLLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
785
- {
786
- return LCALL(fnInfo, argc, argv, (L (*)(L, L, L, L, L, L)) function,
787
- LARG(fnInfo, argv, 0), LARG(fnInfo, argv, 1), LARG(fnInfo, argv, 2),
788
- LARG(fnInfo, argv, 3), LARG(fnInfo, argv, 4), LARG(fnInfo, argv, 5));
789
- }
790
-
791
- static VALUE
792
- rbffi_InvokeLongParams(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
793
- {
794
- void **ffiValues = NULL;
795
- FFIStorage* params = NULL;
796
- L result;
797
-
798
- if (fnInfo->parameterCount > 0) {
799
- ffiValues = ALLOCA_N(void *, fnInfo->parameterCount);
800
- params = ALLOCA_N(FFIStorage, fnInfo->parameterCount);
801
-
802
- rbffi_SetupCallParams(argc, argv,
803
- fnInfo->parameterCount, fnInfo->nativeParameterTypes, params, ffiValues,
804
- fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
805
-
806
- switch (fnInfo->parameterCount) {
807
- case 0:
808
- result = ((L(*)(void)) function)();
809
- break;
810
-
811
- case 1:
812
- result = ((L(*)(L)) function)(*(L *) ffiValues[0]);
813
- break;
814
-
815
- case 2:
816
- result = ((L(*)(L, L)) function)(*(L *) ffiValues[0],
817
- *(L *) ffiValues[1]);
818
- break;
819
-
820
- case 3:
821
- result = ((L(*)(L, L, L)) function)(*(L *) ffiValues[0],
822
- *(L *) ffiValues[1], *(L *) ffiValues[2]);
823
- break;
824
-
825
- case 4:
826
- result = ((L(*)(L, L, L, L)) function)(*(L *) ffiValues[0],
827
- *(L *) ffiValues[1], *(L *) ffiValues[2], *(L *) ffiValues[3]);
828
- break;
829
-
830
- case 5:
831
- result = ((L(*)(L, L, L, L, L)) function)(*(L *) ffiValues[0],
832
- *(L *) ffiValues[1], *(L *) ffiValues[2], *(L *) ffiValues[3],
833
- *(L *) ffiValues[4]);
834
- break;
835
-
836
- case 6:
837
- result = ((L(*)(L, L, L, L, L, L)) function)(*(L *) ffiValues[0],
838
- *(L *) ffiValues[1], *(L *) ffiValues[2], *(L *) ffiValues[3],
839
- *(L *) ffiValues[4], *(L *) ffiValues[5]);
840
- break;
841
-
842
- default:
843
- rb_raise(rb_eRuntimeError, "BUG: should not reach this point");
844
- return Qnil;
845
- }
846
- }
847
-
848
- return returnL(fnInfo, &result);
849
- }
850
-
851
- #endif /* BYPASS_FFI */
852
363
 
853
364
  static void*
854
365
  callback_param(VALUE proc, VALUE cbInfo)
855
366
  {
856
367
  VALUE callback ;
857
- if (proc == Qnil) {
368
+ if (unlikely(proc == Qnil)) {
858
369
  return NULL ;
859
370
  }
860
371
 
@@ -876,6 +387,7 @@ void
876
387
  rbffi_Call_Init(VALUE moduleFFI)
877
388
  {
878
389
  id_to_ptr = rb_intern("to_ptr");
390
+ id_to_native = rb_intern("to_native");
879
391
  id_map_symbol = rb_intern("__map_symbol");
880
392
  }
881
393