ffi 0.6.3-x86-mingw32 → 1.0.1-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/History.txt +7 -0
- data/LICENSE +10 -21
- data/README.rdoc +1 -0
- data/Rakefile +4 -2
- data/ext/ffi_c/AbstractMemory.c +103 -38
- data/ext/ffi_c/AbstractMemory.h +15 -22
- data/ext/ffi_c/Buffer.c +61 -22
- data/ext/ffi_c/Call.c +52 -540
- data/ext/ffi_c/Call.h +1 -1
- data/ext/ffi_c/DataConverter.c +62 -0
- data/ext/ffi_c/DynamicLibrary.c +21 -1
- data/ext/ffi_c/Function.c +315 -30
- data/ext/ffi_c/MappedType.c +146 -0
- data/ext/ffi_c/MappedType.h +57 -0
- data/ext/ffi_c/MemoryPointer.c +12 -33
- data/ext/ffi_c/Platform.c +2 -0
- data/ext/ffi_c/Pointer.c +66 -28
- data/ext/ffi_c/Struct.c +19 -306
- data/ext/ffi_c/Struct.h +6 -0
- data/ext/ffi_c/StructByReference.c +150 -0
- data/ext/ffi_c/StructByReference.h +50 -0
- data/ext/ffi_c/StructLayout.c +25 -14
- data/ext/ffi_c/Type.c +39 -68
- data/ext/ffi_c/Type.h +12 -22
- data/ext/ffi_c/Types.c +20 -5
- data/ext/ffi_c/Types.h +7 -7
- data/ext/ffi_c/Variadic.c +21 -17
- data/ext/ffi_c/extconf.rb +4 -0
- data/ext/ffi_c/ffi.c +8 -2
- data/ext/ffi_c/rbffi.h +1 -0
- data/lib/ffi/autopointer.rb +23 -22
- data/lib/ffi/enum.rb +36 -21
- data/lib/ffi/errno.rb +20 -0
- data/lib/ffi/ffi.rb +13 -80
- data/lib/ffi/io.rb +12 -20
- data/lib/ffi/library.rb +109 -92
- data/lib/ffi/managedstruct.rb +1 -1
- data/lib/ffi/memorypointer.rb +15 -21
- data/lib/ffi/platform.rb +24 -28
- data/lib/ffi/pointer.rb +14 -21
- data/lib/ffi/struct.rb +98 -49
- data/lib/ffi/struct_layout_builder.rb +158 -0
- data/lib/ffi/types.rb +99 -128
- data/lib/ffi/union.rb +20 -0
- data/lib/ffi/variadic.rb +33 -22
- data/lib/ffi_c.so +0 -0
- data/spec/ffi/async_callback_spec.rb +23 -0
- data/spec/ffi/callback_spec.rb +62 -0
- data/spec/ffi/custom_param_type.rb +31 -0
- data/spec/ffi/custom_type_spec.rb +73 -0
- data/spec/ffi/enum_spec.rb +19 -0
- data/spec/ffi/ffi_spec.rb +24 -0
- data/spec/ffi/pointer_spec.rb +15 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
- data/spec/ffi/strptr_spec.rb +36 -0
- data/spec/ffi/struct_packed_spec.rb +46 -0
- data/spec/ffi/struct_spec.rb +19 -5
- data/spec/ffi/typedef_spec.rb +14 -0
- data/tasks/setup.rb +2 -1
- metadata +15 -6
- data/ext/ffi_c/AutoPointer.c +0 -60
- data/ext/ffi_c/AutoPointer.h +0 -18
- data/lib/1.8/ffi_c.so +0 -0
- data/lib/1.9/ffi_c.so +0 -0
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
|
-
*
|
9
|
-
* modification, are permitted provided that the following conditions are met:
|
8
|
+
* This file is part of ruby-ffi.
|
10
9
|
*
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
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
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
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,
|
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 = ¶mStorage[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
|
-
|
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 (
|
108
|
+
switch (paramType->nativeType) {
|
123
109
|
|
124
110
|
case NATIVE_INT8:
|
125
|
-
param->s8 =
|
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 =
|
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
|
-
|
138
|
-
|
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 =
|
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 =
|
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
|
-
|
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",
|
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->
|
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
|
|