ffi 1.12.1 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.appveyor.yml +3 -0
- data/.github/workflows/ci.yml +64 -0
- data/.travis.yml +19 -5
- data/CHANGELOG.md +47 -0
- data/Gemfile +4 -2
- data/Rakefile +24 -43
- data/ext/ffi_c/Buffer.c +2 -2
- data/ext/ffi_c/Call.c +1 -7
- data/ext/ffi_c/ClosurePool.c +11 -14
- data/ext/ffi_c/Function.c +8 -23
- data/ext/ffi_c/FunctionInfo.c +1 -2
- data/ext/ffi_c/LongDouble.c +5 -3
- data/ext/ffi_c/LongDouble.h +0 -4
- data/ext/ffi_c/MemoryPointer.c +1 -1
- data/ext/ffi_c/MethodHandle.c +18 -24
- data/ext/ffi_c/MethodHandle.h +3 -2
- data/ext/ffi_c/Platform.c +1 -0
- data/ext/ffi_c/Pointer.c +1 -1
- data/ext/ffi_c/Struct.c +47 -51
- data/ext/ffi_c/Struct.h +12 -6
- data/ext/ffi_c/StructLayout.c +20 -14
- data/ext/ffi_c/Thread.c +0 -3
- data/ext/ffi_c/Thread.h +0 -3
- data/ext/ffi_c/compat.h +4 -0
- data/ext/ffi_c/extconf.rb +16 -20
- data/ext/ffi_c/libffi/.travis.yml +4 -0
- data/ext/ffi_c/libffi/.travis/build.sh +4 -0
- data/ext/ffi_c/libffi/Makefile.am +2 -1
- data/ext/ffi_c/libffi/README.md +7 -1
- data/ext/ffi_c/libffi/configure.ac +25 -9
- data/ext/ffi_c/libffi/include/ffi.h.in +8 -0
- data/ext/ffi_c/libffi/libffi.map.in +8 -12
- data/ext/ffi_c/libffi/libtool-version +1 -1
- data/ext/ffi_c/libffi/src/aarch64/ffi.c +6 -0
- data/ext/ffi_c/libffi/src/aarch64/sysv.S +13 -2
- data/ext/ffi_c/libffi/src/closures.c +10 -4
- data/ext/ffi_c/libffi/src/pa/ffi.c +46 -91
- data/ext/ffi_c/libffi/src/pa/ffitarget.h +1 -6
- data/ext/ffi_c/libffi/src/pa/hpux32.S +4 -2
- data/ext/ffi_c/libffi/src/pa/linux.S +4 -2
- data/ext/ffi_c/libffi/src/powerpc/sysv.S +5 -7
- data/ext/ffi_c/libffi/src/x86/ffi.c +7 -4
- data/ext/ffi_c/libffi/src/x86/ffi64.c +10 -8
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +15 -2
- data/ext/ffi_c/libffi/src/x86/ffiw64.c +10 -8
- data/ext/ffi_c/libffi/src/x86/sysv.S +13 -4
- data/ext/ffi_c/libffi/src/x86/unix64.S +58 -2
- data/ext/ffi_c/libffi/src/x86/win64.S +4 -1
- data/ffi.gemspec +1 -1
- data/lib/ffi.rb +10 -2
- data/lib/ffi/library.rb +5 -1
- data/lib/ffi/platform.rb +6 -2
- data/lib/ffi/platform/arm-linux/types.conf +32 -4
- data/lib/ffi/platform/i386-windows/types.conf +26 -79
- data/lib/ffi/platform/powerpc-linux/types.conf +32 -2
- data/lib/ffi/platform/powerpc-openbsd/types.conf +156 -0
- data/lib/ffi/platform/sparcv9-openbsd/types.conf +156 -0
- data/lib/ffi/platform/x86_64-darwin/types.conf +4 -0
- data/lib/ffi/platform/x86_64-dragonflybsd/types.conf +4 -22
- data/lib/ffi/platform/x86_64-linux/types.conf +21 -0
- data/lib/ffi/platform/x86_64-windows/types.conf +10 -78
- data/lib/ffi/pointer.rb +19 -12
- data/lib/ffi/struct.rb +9 -4
- data/lib/ffi/tools/types_generator.rb +2 -0
- data/lib/ffi/version.rb +1 -1
- data/samples/getlogin.rb +1 -1
- data/samples/getpid.rb +1 -1
- data/samples/gettimeofday.rb +8 -8
- data/samples/hello.rb +2 -1
- data/samples/inotify.rb +1 -1
- data/samples/pty.rb +1 -2
- data/samples/qsort.rb +0 -1
- metadata +6 -4
- data/samples/sample_helper.rb +0 -6
data/ext/ffi_c/Function.c
CHANGED
@@ -99,26 +99,8 @@ static VALUE async_cb_event(void *);
|
|
99
99
|
static VALUE async_cb_call(void *);
|
100
100
|
#endif
|
101
101
|
|
102
|
-
#ifdef HAVE_RUBY_THREAD_HAS_GVL_P
|
103
102
|
extern int ruby_thread_has_gvl_p(void);
|
104
|
-
#define rbffi_thread_has_gvl_p(frame) ruby_thread_has_gvl_p()
|
105
|
-
#else
|
106
|
-
static int rbffi_thread_has_gvl_p(rbffi_frame_t *frame)
|
107
|
-
{
|
108
|
-
return frame != NULL && frame->has_gvl;
|
109
|
-
}
|
110
|
-
#endif
|
111
|
-
|
112
|
-
#ifdef HAVE_RUBY_NATIVE_THREAD_P
|
113
103
|
extern int ruby_native_thread_p(void);
|
114
|
-
#define rbffi_native_thread_p(frame) ruby_native_thread_p()
|
115
|
-
#else
|
116
|
-
static int rbffi_native_thread_p(rbffi_frame_t *frame)
|
117
|
-
{
|
118
|
-
return frame != NULL;
|
119
|
-
}
|
120
|
-
#endif
|
121
|
-
|
122
104
|
|
123
105
|
VALUE rbffi_FunctionClass = Qnil;
|
124
106
|
|
@@ -476,8 +458,8 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
|
|
476
458
|
|
477
459
|
if (cb.frame != NULL) cb.frame->exc = Qnil;
|
478
460
|
|
479
|
-
if (
|
480
|
-
if(
|
461
|
+
if (ruby_native_thread_p()) {
|
462
|
+
if(ruby_thread_has_gvl_p()) {
|
481
463
|
callback_with_gvl(&cb);
|
482
464
|
} else {
|
483
465
|
rb_thread_call_with_gvl(callback_with_gvl, &cb);
|
@@ -721,7 +703,7 @@ invoke_callback(VALUE data)
|
|
721
703
|
param = rb_float_new(*(double *) parameters[i]);
|
722
704
|
break;
|
723
705
|
case NATIVE_LONGDOUBLE:
|
724
|
-
|
706
|
+
param = rbffi_longdouble_new(*(long double *) parameters[i]);
|
725
707
|
break;
|
726
708
|
case NATIVE_STRING:
|
727
709
|
param = (*(void **) parameters[i] != NULL) ? rb_str_new2(*(char **) parameters[i]) : Qnil;
|
@@ -793,6 +775,9 @@ invoke_callback(VALUE data)
|
|
793
775
|
case NATIVE_FLOAT64:
|
794
776
|
*((double *) retval) = NUM2DBL(rbReturnValue);
|
795
777
|
break;
|
778
|
+
case NATIVE_LONGDOUBLE:
|
779
|
+
*((long double *) retval) = rbffi_num2longdouble(rbReturnValue);
|
780
|
+
break;
|
796
781
|
case NATIVE_POINTER:
|
797
782
|
if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
|
798
783
|
*((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
|
@@ -864,9 +849,9 @@ callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errm
|
|
864
849
|
FunctionType* fnInfo = (FunctionType *) ctx;
|
865
850
|
ffi_status ffiStatus;
|
866
851
|
|
867
|
-
ffiStatus =
|
852
|
+
ffiStatus = ffi_prep_closure_loc(code, &fnInfo->ffi_cif, callback_invoke, closure, code);
|
868
853
|
if (ffiStatus != FFI_OK) {
|
869
|
-
snprintf(errmsg, errmsgsize, "
|
854
|
+
snprintf(errmsg, errmsgsize, "ffi_prep_closure_loc failed. status=%#x", ffiStatus);
|
870
855
|
return false;
|
871
856
|
}
|
872
857
|
|
data/ext/ffi_c/FunctionInfo.c
CHANGED
@@ -172,7 +172,7 @@ fntype_initialize(int argc, VALUE* argv, VALUE self)
|
|
172
172
|
VALUE typeName = rb_funcall2(rbReturnType, rb_intern("inspect"), 0, NULL);
|
173
173
|
rb_raise(rb_eTypeError, "Invalid return type (%s)", RSTRING_PTR(typeName));
|
174
174
|
}
|
175
|
-
|
175
|
+
|
176
176
|
if (rb_obj_is_kind_of(fnInfo->rbReturnType, rbffi_StructByValueClass)) {
|
177
177
|
fnInfo->hasStruct = true;
|
178
178
|
}
|
@@ -180,7 +180,6 @@ fntype_initialize(int argc, VALUE* argv, VALUE self)
|
|
180
180
|
Data_Get_Struct(fnInfo->rbReturnType, Type, fnInfo->returnType);
|
181
181
|
fnInfo->ffiReturnType = fnInfo->returnType->ffiType;
|
182
182
|
|
183
|
-
|
184
183
|
#if defined(X86_WIN32)
|
185
184
|
rbConventionStr = (rbConvention != Qnil) ? rb_funcall2(rbConvention, rb_intern("to_s"), 0, NULL) : Qnil;
|
186
185
|
fnInfo->abi = (rbConventionStr != Qnil && strcmp(StringValueCStr(rbConventionStr), "stdcall") == 0)
|
data/ext/ffi_c/LongDouble.c
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#include <stdarg.h>
|
4
4
|
#include <float.h>
|
5
5
|
|
6
|
-
#if defined (__CYGWIN__) || defined(__INTERIX)
|
6
|
+
#if defined (__CYGWIN__) || defined(__INTERIX) || defined(_MSC_VER)
|
7
7
|
# define strtold(str, endptr) ((long double) strtod((str), (endptr)))
|
8
8
|
#endif /* defined (__CYGWIN__) */
|
9
9
|
|
@@ -21,7 +21,7 @@ rbffi_longdouble_new(long double ld)
|
|
21
21
|
|
22
22
|
if (RTEST(rb_cBigDecimal) && rb_cBigDecimal != rb_cObject) {
|
23
23
|
char buf[128];
|
24
|
-
return rb_funcall(
|
24
|
+
return rb_funcall(rb_mKernel, rb_intern("BigDecimal"), 1, rb_str_new(buf, sprintf(buf, "%.35Le", ld)));
|
25
25
|
}
|
26
26
|
|
27
27
|
/* Fall through to handling as a float */
|
@@ -41,7 +41,9 @@ rbffi_num2longdouble(VALUE value)
|
|
41
41
|
|
42
42
|
if (RTEST(rb_cBigDecimal) && rb_cBigDecimal != rb_cObject && RTEST(rb_obj_is_kind_of(value, rb_cBigDecimal))) {
|
43
43
|
VALUE s = rb_funcall(value, rb_intern("to_s"), 1, rb_str_new2("E"));
|
44
|
-
|
44
|
+
long double ret = strtold(RSTRING_PTR(s), NULL);
|
45
|
+
RB_GC_GUARD(s);
|
46
|
+
return ret;
|
45
47
|
}
|
46
48
|
|
47
49
|
/* Fall through to handling as a float */
|
data/ext/ffi_c/LongDouble.h
CHANGED
data/ext/ffi_c/MemoryPointer.c
CHANGED
@@ -112,7 +112,7 @@ memptr_malloc(VALUE self, long size, long count, bool clear)
|
|
112
112
|
p->memory.typeSize = (int) size;
|
113
113
|
p->memory.size = msize;
|
114
114
|
/* ensure the memory is aligned on at least a 8 byte boundary */
|
115
|
-
p->memory.address = (char *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~
|
115
|
+
p->memory.address = (char *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7ULL);
|
116
116
|
p->allocated = true;
|
117
117
|
|
118
118
|
if (clear && p->memory.size > 0) {
|
data/ext/ffi_c/MethodHandle.c
CHANGED
@@ -68,9 +68,6 @@
|
|
68
68
|
#ifndef roundup
|
69
69
|
# define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
|
70
70
|
#endif
|
71
|
-
#ifdef _WIN32
|
72
|
-
typedef char* caddr_t;
|
73
|
-
#endif
|
74
71
|
|
75
72
|
#ifdef USE_RAW
|
76
73
|
# define METHOD_CLOSURE ffi_raw_closure
|
@@ -123,20 +120,15 @@ rbffi_MethodHandle_Free(MethodHandle* handle)
|
|
123
120
|
}
|
124
121
|
}
|
125
122
|
|
126
|
-
|
127
|
-
rbffi_MethodHandle_CodeAddress(MethodHandle* handle)
|
123
|
+
rbffi_function_anyargs rbffi_MethodHandle_CodeAddress(MethodHandle* handle)
|
128
124
|
{
|
129
|
-
return handle->closure->code;
|
125
|
+
return (rbffi_function_anyargs) handle->closure->code;
|
130
126
|
}
|
131
127
|
|
132
128
|
#ifndef CUSTOM_TRAMPOLINE
|
133
129
|
static void attached_method_invoke(ffi_cif* cif, void* retval, METHOD_PARAMS parameters, void* user_data);
|
134
130
|
|
135
|
-
static ffi_type* methodHandleParamTypes[]
|
136
|
-
&ffi_type_sint,
|
137
|
-
&ffi_type_pointer,
|
138
|
-
&ffi_type_ulong,
|
139
|
-
};
|
131
|
+
static ffi_type* methodHandleParamTypes[3];
|
140
132
|
|
141
133
|
static ffi_cif mh_cif;
|
142
134
|
|
@@ -148,10 +140,10 @@ prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t er
|
|
148
140
|
#if defined(USE_RAW)
|
149
141
|
ffiStatus = ffi_prep_raw_closure(code, &mh_cif, attached_method_invoke, closure);
|
150
142
|
#else
|
151
|
-
ffiStatus =
|
143
|
+
ffiStatus = ffi_prep_closure_loc(code, &mh_cif, attached_method_invoke, closure, code);
|
152
144
|
#endif
|
153
145
|
if (ffiStatus != FFI_OK) {
|
154
|
-
snprintf(errmsg, errmsgsize, "
|
146
|
+
snprintf(errmsg, errmsgsize, "ffi_prep_closure_loc failed. status=%#x", ffiStatus);
|
155
147
|
return false;
|
156
148
|
}
|
157
149
|
|
@@ -237,7 +229,7 @@ custom_trampoline(int argc, VALUE* argv, VALUE self, Closure* handle)
|
|
237
229
|
|
238
230
|
#elif defined(__i386__) && 0
|
239
231
|
|
240
|
-
static VALUE custom_trampoline(
|
232
|
+
static VALUE custom_trampoline(void *args, Closure*);
|
241
233
|
#define TRAMPOLINE_CTX_MAGIC (0xfee1dead)
|
242
234
|
#define TRAMPOLINE_FUN_MAGIC (0xbeefcafe)
|
243
235
|
|
@@ -269,7 +261,7 @@ __asm__(
|
|
269
261
|
);
|
270
262
|
|
271
263
|
static VALUE
|
272
|
-
custom_trampoline(
|
264
|
+
custom_trampoline(void *args, Closure* handle)
|
273
265
|
{
|
274
266
|
FunctionType* fnInfo = (FunctionType *) handle->info;
|
275
267
|
return (*fnInfo->invoke)(*(int *) args, *(VALUE **) (args + 4), handle->function, fnInfo);
|
@@ -286,10 +278,10 @@ static long trampoline_ctx_offset, trampoline_func_offset;
|
|
286
278
|
static long
|
287
279
|
trampoline_offset(int off, const long value)
|
288
280
|
{
|
289
|
-
|
290
|
-
for (ptr = (
|
281
|
+
char *ptr;
|
282
|
+
for (ptr = (char *) &ffi_trampoline + off; ptr < (char *) &ffi_trampoline_end; ++ptr) {
|
291
283
|
if (*(long *) ptr == value) {
|
292
|
-
return ptr - (
|
284
|
+
return ptr - (char *) &ffi_trampoline;
|
293
285
|
}
|
294
286
|
}
|
295
287
|
|
@@ -315,12 +307,10 @@ trampoline_offsets(long* ctxOffset, long* fnOffset)
|
|
315
307
|
static bool
|
316
308
|
prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize)
|
317
309
|
{
|
318
|
-
|
319
|
-
|
320
|
-
memcpy(ptr, &ffi_trampoline, trampoline_size());
|
310
|
+
memcpy(code, (void*) &ffi_trampoline, trampoline_size());
|
321
311
|
/* Patch the context and function addresses into the stub code */
|
322
|
-
*(intptr_t *)(
|
323
|
-
*(intptr_t *)(
|
312
|
+
*(intptr_t *)((char*)code + trampoline_ctx_offset) = (intptr_t) closure;
|
313
|
+
*(intptr_t *)((char*)code + trampoline_func_offset) = (intptr_t) custom_trampoline;
|
324
314
|
|
325
315
|
return true;
|
326
316
|
}
|
@@ -328,7 +318,7 @@ prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t er
|
|
328
318
|
static long
|
329
319
|
trampoline_size(void)
|
330
320
|
{
|
331
|
-
return (
|
321
|
+
return (char *) &ffi_trampoline_end - (char *) &ffi_trampoline;
|
332
322
|
}
|
333
323
|
|
334
324
|
#endif /* CUSTOM_TRAMPOLINE */
|
@@ -348,6 +338,10 @@ rbffi_MethodHandle_Init(VALUE module)
|
|
348
338
|
rb_raise(rb_eFatal, "Could not locate offsets in trampoline code");
|
349
339
|
}
|
350
340
|
#else
|
341
|
+
methodHandleParamTypes[0] = &ffi_type_sint;
|
342
|
+
methodHandleParamTypes[1] = &ffi_type_pointer;
|
343
|
+
methodHandleParamTypes[2] = &ffi_type_ulong;
|
344
|
+
|
351
345
|
ffiStatus = ffi_prep_cif(&mh_cif, FFI_DEFAULT_ABI, 3, &ffi_type_ulong,
|
352
346
|
methodHandleParamTypes);
|
353
347
|
if (ffiStatus != FFI_OK) {
|
data/ext/ffi_c/MethodHandle.h
CHANGED
@@ -37,14 +37,15 @@ extern "C" {
|
|
37
37
|
#include <ruby.h>
|
38
38
|
#include "Function.h"
|
39
39
|
|
40
|
-
|
40
|
+
|
41
41
|
typedef struct MethodHandlePool MethodHandlePool;
|
42
42
|
typedef struct MethodHandle MethodHandle;
|
43
|
+
typedef VALUE (*rbffi_function_anyargs)(int argc, VALUE* argv, VALUE self);
|
43
44
|
|
44
45
|
|
45
46
|
MethodHandle* rbffi_MethodHandle_Alloc(FunctionType* fnInfo, void* function);
|
46
47
|
void rbffi_MethodHandle_Free(MethodHandle* handle);
|
47
|
-
|
48
|
+
rbffi_function_anyargs rbffi_MethodHandle_CodeAddress(MethodHandle* handle);
|
48
49
|
void rbffi_MethodHandle_Init(VALUE module);
|
49
50
|
|
50
51
|
#ifdef __cplusplus
|
data/ext/ffi_c/Platform.c
CHANGED
data/ext/ffi_c/Pointer.c
CHANGED
@@ -183,7 +183,7 @@ ptr_initialize_copy(VALUE self, VALUE other)
|
|
183
183
|
|
184
184
|
dst->allocated = true;
|
185
185
|
dst->autorelease = true;
|
186
|
-
dst->memory.address = (void *) (((uintptr_t) dst->storage + 0x7) & (uintptr_t) ~
|
186
|
+
dst->memory.address = (void *) (((uintptr_t) dst->storage + 0x7) & (uintptr_t) ~0x7ULL);
|
187
187
|
dst->memory.size = src->size;
|
188
188
|
dst->memory.typeSize = src->typeSize;
|
189
189
|
|
data/ext/ffi_c/Struct.c
CHANGED
@@ -90,7 +90,7 @@ struct_allocate(VALUE klass)
|
|
90
90
|
{
|
91
91
|
Struct* s;
|
92
92
|
VALUE obj = Data_Make_Struct(klass, Struct, struct_mark, struct_free, s);
|
93
|
-
|
93
|
+
|
94
94
|
s->rbPointer = Qnil;
|
95
95
|
s->rbLayout = Qnil;
|
96
96
|
|
@@ -112,7 +112,7 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
112
112
|
int nargs;
|
113
113
|
|
114
114
|
Data_Get_Struct(self, Struct, s);
|
115
|
-
|
115
|
+
|
116
116
|
nargs = rb_scan_args(argc, argv, "01*", &rbPointer, &rest);
|
117
117
|
|
118
118
|
/* Call up into ruby code to adjust the layout */
|
@@ -127,7 +127,7 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
127
127
|
}
|
128
128
|
|
129
129
|
Data_Get_Struct(s->rbLayout, StructLayout, s->layout);
|
130
|
-
|
130
|
+
|
131
131
|
if (rbPointer != Qnil) {
|
132
132
|
s->pointer = MEMORY(rbPointer);
|
133
133
|
s->rbPointer = rbPointer;
|
@@ -148,16 +148,16 @@ struct_initialize_copy(VALUE self, VALUE other)
|
|
148
148
|
{
|
149
149
|
Struct* src;
|
150
150
|
Struct* dst;
|
151
|
-
|
151
|
+
|
152
152
|
Data_Get_Struct(self, Struct, dst);
|
153
153
|
Data_Get_Struct(other, Struct, src);
|
154
154
|
if (dst == src) {
|
155
155
|
return self;
|
156
156
|
}
|
157
|
-
|
157
|
+
|
158
158
|
dst->rbLayout = src->rbLayout;
|
159
159
|
dst->layout = src->layout;
|
160
|
-
|
160
|
+
|
161
161
|
/*
|
162
162
|
* A new MemoryPointer instance is allocated here instead of just calling
|
163
163
|
* #dup on rbPointer, since the Pointer may not know its length, or may
|
@@ -176,7 +176,7 @@ struct_initialize_copy(VALUE self, VALUE other)
|
|
176
176
|
dst->rbReferences = ALLOC_N(VALUE, dst->layout->referenceFieldCount);
|
177
177
|
memcpy(dst->rbReferences, src->rbReferences, dst->layout->referenceFieldCount * sizeof(VALUE));
|
178
178
|
}
|
179
|
-
|
179
|
+
|
180
180
|
return self;
|
181
181
|
}
|
182
182
|
|
@@ -279,24 +279,25 @@ store_reference_value(StructField* f, Struct* s, VALUE value)
|
|
279
279
|
}
|
280
280
|
|
281
281
|
|
282
|
-
static
|
282
|
+
static StructField *
|
283
283
|
struct_field(Struct* s, VALUE fieldName)
|
284
284
|
{
|
285
285
|
StructLayout* layout = s->layout;
|
286
|
-
|
287
|
-
|
288
|
-
if
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
286
|
+
struct field_cache_entry *p_ce = FIELD_CACHE_LOOKUP(layout, fieldName);
|
287
|
+
|
288
|
+
/* Do a hash lookup only if cache entry is empty or fieldName is unexpected? */
|
289
|
+
if (unlikely(!SYMBOL_P(fieldName) || !p_ce->fieldName || p_ce->fieldName != fieldName)) {
|
290
|
+
VALUE rbField = rb_hash_aref(layout->rbFieldMap, fieldName);
|
291
|
+
if (unlikely(NIL_P(rbField))) {
|
292
|
+
VALUE str = rb_funcall2(fieldName, id_to_s, 0, NULL);
|
293
|
+
rb_raise(rb_eArgError, "No such field '%s'", StringValuePtr(str));
|
294
|
+
}
|
295
|
+
/* Write the retrieved coder to the cache */
|
296
|
+
p_ce->fieldName = fieldName;
|
297
|
+
p_ce->field = (StructField *) DATA_PTR(rbField);
|
297
298
|
}
|
298
299
|
|
299
|
-
return
|
300
|
+
return p_ce->field;
|
300
301
|
}
|
301
302
|
|
302
303
|
/*
|
@@ -308,22 +309,19 @@ static VALUE
|
|
308
309
|
struct_aref(VALUE self, VALUE fieldName)
|
309
310
|
{
|
310
311
|
Struct* s;
|
311
|
-
VALUE rbField;
|
312
312
|
StructField* f;
|
313
313
|
|
314
314
|
s = struct_validate(self);
|
315
315
|
|
316
|
-
|
317
|
-
f = (StructField *) DATA_PTR(rbField);
|
318
|
-
|
316
|
+
f = struct_field(s, fieldName);
|
319
317
|
if (f->get != NULL) {
|
320
318
|
return (*f->get)(f, s);
|
321
|
-
|
319
|
+
|
322
320
|
} else if (f->memoryOp != NULL) {
|
323
321
|
return (*f->memoryOp->get)(s->pointer, f->offset);
|
324
322
|
|
325
323
|
} else {
|
326
|
-
|
324
|
+
VALUE rbField = rb_hash_aref(s->layout->rbFieldMap, fieldName);
|
327
325
|
/* call up to the ruby code to fetch the value */
|
328
326
|
return rb_funcall2(rbField, id_get, 1, &s->rbPointer);
|
329
327
|
}
|
@@ -340,22 +338,20 @@ static VALUE
|
|
340
338
|
struct_aset(VALUE self, VALUE fieldName, VALUE value)
|
341
339
|
{
|
342
340
|
Struct* s;
|
343
|
-
VALUE rbField;
|
344
341
|
StructField* f;
|
345
342
|
|
346
|
-
|
347
343
|
s = struct_validate(self);
|
348
344
|
|
349
|
-
|
350
|
-
f = (StructField *) DATA_PTR(rbField);
|
345
|
+
f = struct_field(s, fieldName);
|
351
346
|
if (f->put != NULL) {
|
352
347
|
(*f->put)(f, s, value);
|
353
348
|
|
354
349
|
} else if (f->memoryOp != NULL) {
|
355
350
|
|
356
351
|
(*f->memoryOp->put)(s->pointer, f->offset, value);
|
357
|
-
|
352
|
+
|
358
353
|
} else {
|
354
|
+
VALUE rbField = rb_hash_aref(s->layout->rbFieldMap, fieldName);
|
359
355
|
/* call up to the ruby code to set the value */
|
360
356
|
VALUE argv[2];
|
361
357
|
argv[0] = s->rbPointer;
|
@@ -366,7 +362,7 @@ struct_aset(VALUE self, VALUE fieldName, VALUE value)
|
|
366
362
|
if (f->referenceRequired) {
|
367
363
|
store_reference_value(f, s, value);
|
368
364
|
}
|
369
|
-
|
365
|
+
|
370
366
|
return value;
|
371
367
|
}
|
372
368
|
|
@@ -389,7 +385,7 @@ struct_set_pointer(VALUE self, VALUE pointer)
|
|
389
385
|
return Qnil;
|
390
386
|
}
|
391
387
|
|
392
|
-
|
388
|
+
|
393
389
|
Data_Get_Struct(self, Struct, s);
|
394
390
|
Data_Get_Struct(pointer, AbstractMemory, memory);
|
395
391
|
layout = struct_layout(self);
|
@@ -398,7 +394,7 @@ struct_set_pointer(VALUE self, VALUE pointer)
|
|
398
394
|
rb_raise(rb_eArgError, "memory of %ld bytes too small for struct %s (expected at least %ld)",
|
399
395
|
memory->size, rb_obj_classname(self), (long) layout->base.ffiType->size);
|
400
396
|
}
|
401
|
-
|
397
|
+
|
402
398
|
s->pointer = MEMORY(pointer);
|
403
399
|
s->rbPointer = pointer;
|
404
400
|
rb_ivar_set(self, id_pointer_ivar, pointer);
|
@@ -491,7 +487,7 @@ struct_order(int argc, VALUE* argv, VALUE self)
|
|
491
487
|
VALUE retval = rb_obj_dup(self);
|
492
488
|
VALUE rbPointer = rb_funcall2(s->rbPointer, rb_intern("order"), argc, argv);
|
493
489
|
struct_set_pointer(retval, rbPointer);
|
494
|
-
|
490
|
+
|
495
491
|
return retval;
|
496
492
|
}
|
497
493
|
}
|
@@ -527,7 +523,7 @@ static VALUE
|
|
527
523
|
inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField)
|
528
524
|
{
|
529
525
|
InlineArray* array;
|
530
|
-
|
526
|
+
|
531
527
|
Data_Get_Struct(self, InlineArray, array);
|
532
528
|
array->rbMemory = rbMemory;
|
533
529
|
array->rbField = rbField;
|
@@ -536,12 +532,12 @@ inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField)
|
|
536
532
|
Data_Get_Struct(rbField, StructField, array->field);
|
537
533
|
Data_Get_Struct(array->field->rbType, ArrayType, array->arrayType);
|
538
534
|
Data_Get_Struct(array->arrayType->rbComponentType, Type, array->componentType);
|
539
|
-
|
535
|
+
|
540
536
|
array->op = get_memory_op(array->componentType);
|
541
537
|
if (array->op == NULL && array->componentType->nativeType == NATIVE_MAPPED) {
|
542
538
|
array->op = get_memory_op(((MappedType *) array->componentType)->type);
|
543
539
|
}
|
544
|
-
|
540
|
+
|
545
541
|
array->length = array->arrayType->length;
|
546
542
|
|
547
543
|
return self;
|
@@ -585,15 +581,15 @@ inline_array_aref(VALUE self, VALUE rbIndex)
|
|
585
581
|
Data_Get_Struct(self, InlineArray, array);
|
586
582
|
|
587
583
|
if (array->op != NULL) {
|
588
|
-
VALUE rbNativeValue = array->op->get(array->memory,
|
584
|
+
VALUE rbNativeValue = array->op->get(array->memory,
|
589
585
|
inline_array_offset(array, NUM2INT(rbIndex)));
|
590
586
|
if (unlikely(array->componentType->nativeType == NATIVE_MAPPED)) {
|
591
|
-
return rb_funcall(((MappedType *) array->componentType)->rbConverter,
|
587
|
+
return rb_funcall(((MappedType *) array->componentType)->rbConverter,
|
592
588
|
rb_intern("from_native"), 2, rbNativeValue, Qnil);
|
593
589
|
} else {
|
594
|
-
return rbNativeValue;
|
590
|
+
return rbNativeValue;
|
595
591
|
}
|
596
|
-
|
592
|
+
|
597
593
|
} else if (array->componentType->nativeType == NATIVE_STRUCT) {
|
598
594
|
VALUE rbOffset = INT2NUM(inline_array_offset(array, NUM2INT(rbIndex)));
|
599
595
|
VALUE rbLength = INT2NUM(array->componentType->ffiType->size);
|
@@ -622,12 +618,12 @@ inline_array_aset(VALUE self, VALUE rbIndex, VALUE rbValue)
|
|
622
618
|
|
623
619
|
if (array->op != NULL) {
|
624
620
|
if (unlikely(array->componentType->nativeType == NATIVE_MAPPED)) {
|
625
|
-
rbValue = rb_funcall(((MappedType *) array->componentType)->rbConverter,
|
621
|
+
rbValue = rb_funcall(((MappedType *) array->componentType)->rbConverter,
|
626
622
|
rb_intern("to_native"), 2, rbValue, Qnil);
|
627
623
|
}
|
628
624
|
array->op->put(array->memory, inline_array_offset(array, NUM2INT(rbIndex)),
|
629
625
|
rbValue);
|
630
|
-
|
626
|
+
|
631
627
|
} else if (array->componentType->nativeType == NATIVE_STRUCT) {
|
632
628
|
int offset = inline_array_offset(array, NUM2INT(rbIndex));
|
633
629
|
Struct* s;
|
@@ -665,11 +661,11 @@ static VALUE
|
|
665
661
|
inline_array_each(VALUE self)
|
666
662
|
{
|
667
663
|
InlineArray* array;
|
668
|
-
|
664
|
+
|
669
665
|
int i;
|
670
666
|
|
671
667
|
Data_Get_Struct(self, InlineArray, array);
|
672
|
-
|
668
|
+
|
673
669
|
for (i = 0; i < array->length; ++i) {
|
674
670
|
rb_yield(inline_array_aref(self, INT2FIX(i)));
|
675
671
|
}
|
@@ -692,7 +688,7 @@ inline_array_to_a(VALUE self)
|
|
692
688
|
Data_Get_Struct(self, InlineArray, array);
|
693
689
|
obj = rb_ary_new2(array->length);
|
694
690
|
|
695
|
-
|
691
|
+
|
696
692
|
for (i = 0; i < array->length; ++i) {
|
697
693
|
rb_ary_push(obj, inline_array_aref(self, INT2FIX(i)));
|
698
694
|
}
|
@@ -713,7 +709,7 @@ inline_array_to_s(VALUE self)
|
|
713
709
|
VALUE argv[2];
|
714
710
|
|
715
711
|
Data_Get_Struct(self, InlineArray, array);
|
716
|
-
|
712
|
+
|
717
713
|
if (array->componentType->nativeType != NATIVE_INT8 && array->componentType->nativeType != NATIVE_UINT8) {
|
718
714
|
VALUE dummy = Qnil;
|
719
715
|
return rb_call_super(0, &dummy);
|
@@ -734,7 +730,7 @@ static VALUE
|
|
734
730
|
inline_array_to_ptr(VALUE self)
|
735
731
|
{
|
736
732
|
InlineArray* array;
|
737
|
-
|
733
|
+
|
738
734
|
Data_Get_Struct(self, InlineArray, array);
|
739
735
|
|
740
736
|
return rb_funcall(array->rbMemory, rb_intern("slice"), 2,
|
@@ -778,7 +774,7 @@ rbffi_Struct_Init(VALUE moduleFFI)
|
|
778
774
|
/*
|
779
775
|
* Document-class: FFI::StructLayout::CharArray < FFI::Struct::InlineArray
|
780
776
|
*/
|
781
|
-
rbffi_StructLayoutCharArrayClass = rb_define_class_under(rbffi_StructLayoutClass, "CharArray",
|
777
|
+
rbffi_StructLayoutCharArrayClass = rb_define_class_under(rbffi_StructLayoutClass, "CharArray",
|
782
778
|
rbffi_StructInlineArrayClass);
|
783
779
|
rb_global_variable(&rbffi_StructLayoutCharArrayClass);
|
784
780
|
|
@@ -787,7 +783,7 @@ rbffi_Struct_Init(VALUE moduleFFI)
|
|
787
783
|
rb_define_method(StructClass, "initialize", struct_initialize, -1);
|
788
784
|
rb_define_method(StructClass, "initialize_copy", struct_initialize_copy, 1);
|
789
785
|
rb_define_method(StructClass, "order", struct_order, -1);
|
790
|
-
|
786
|
+
|
791
787
|
rb_define_alias(rb_singleton_class(StructClass), "alloc_in", "new");
|
792
788
|
rb_define_alias(rb_singleton_class(StructClass), "alloc_out", "new");
|
793
789
|
rb_define_alias(rb_singleton_class(StructClass), "alloc_inout", "new");
|