fiddle 1.0.9 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/Rakefile +12 -0
- data/ext/fiddle/closure.c +131 -33
- data/ext/fiddle/conversions.c +64 -11
- data/ext/fiddle/conversions.h +2 -0
- data/ext/fiddle/extconf.rb +15 -27
- data/ext/fiddle/fiddle.c +215 -56
- data/ext/fiddle/fiddle.h +44 -6
- data/ext/fiddle/function.c +7 -2
- data/ext/fiddle/handle.c +121 -7
- data/ext/fiddle/memory_view.c +6 -8
- data/ext/fiddle/pointer.c +57 -15
- data/ext/fiddle/win32/libffi-config.rb +5 -5
- data/fiddle.gemspec +1 -8
- data/lib/fiddle/closure.rb +25 -0
- data/lib/fiddle/cparser.rb +28 -14
- data/lib/fiddle/import.rb +2 -0
- data/lib/fiddle/pack.rb +30 -17
- data/lib/fiddle/struct.rb +71 -0
- data/lib/fiddle/value.rb +13 -15
- data/lib/fiddle/version.rb +1 -1
- data/lib/fiddle.rb +34 -1
- metadata +8 -53
- data/bin/downloader.rb +0 -331
- data/bin/extlibs.rb +0 -262
- data/ext/fiddle/extlibs +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17a63516f0bbb623b730ccaa32e98df18c1b3c447b99027b82125ab788363175
|
4
|
+
data.tar.gz: 6b834175e32765e9a13edfb4f32390b48d8914d5bbe8e0b50b215f409b4ee192
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c0bf76f5288d9241daa1ec0f2dae597a33a428afb893d7cf274cfd6c247c99eb93280f4fe1883b2fbabeb844cae9e272df2209feaba69cd781b689f772fb3f6
|
7
|
+
data.tar.gz: '038a55b29aafc16824c2d0498be0e22851c0f5e97956ee961220cd606dcb55a6615cdaca8ec0481e1fb6e9a4d28ec544ac86e78cf640c0e0cb551e65266b0a7d'
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Fiddle
|
2
2
|
|
3
|
-
[![
|
3
|
+
[![CI](https://github.com/ruby/fiddle/actions/workflows/ci.yml/badge.svg)](https://github.com/ruby/fiddle/actions/workflows/ci.yml)
|
4
4
|
|
5
5
|
A libffi wrapper for Ruby.
|
6
6
|
|
data/Rakefile
CHANGED
@@ -5,6 +5,18 @@ task :test do
|
|
5
5
|
ruby("test/run.rb")
|
6
6
|
end
|
7
7
|
|
8
|
+
namespace :version do
|
9
|
+
desc "Bump version"
|
10
|
+
task :bump do
|
11
|
+
version_rb_path = "lib/fiddle/version.rb"
|
12
|
+
version_rb = File.read(version_rb_path).gsub(/VERSION = "(.+?)"/) do
|
13
|
+
version = $1
|
14
|
+
"VERSION = \"#{version.succ}\""
|
15
|
+
end
|
16
|
+
File.write(version_rb_path, version_rb)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
8
20
|
require 'rake/extensiontask'
|
9
21
|
Rake::ExtensionTask.new("fiddle")
|
10
22
|
Rake::ExtensionTask.new("-test-/memory_view")
|
data/ext/fiddle/closure.c
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#include <fiddle.h>
|
2
|
+
#include <stdbool.h>
|
2
3
|
#include <ruby/thread.h>
|
3
4
|
|
4
5
|
int ruby_thread_has_gvl_p(void); /* from internal.h */
|
@@ -54,8 +55,13 @@ closure_memsize(const void * ptr)
|
|
54
55
|
}
|
55
56
|
|
56
57
|
const rb_data_type_t closure_data_type = {
|
57
|
-
"fiddle/closure",
|
58
|
-
|
58
|
+
.wrap_struct_name = "fiddle/closure",
|
59
|
+
.function = {
|
60
|
+
.dmark = 0,
|
61
|
+
.dfree = dealloc,
|
62
|
+
.dsize = closure_memsize
|
63
|
+
},
|
64
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
59
65
|
};
|
60
66
|
|
61
67
|
struct callback_args {
|
@@ -90,7 +96,7 @@ with_gvl_callback(void *ptr)
|
|
90
96
|
case TYPE_INT:
|
91
97
|
rb_ary_push(params, INT2NUM(*(int *)x->args[i]));
|
92
98
|
break;
|
93
|
-
case
|
99
|
+
case TYPE_UINT:
|
94
100
|
rb_ary_push(params, UINT2NUM(*(unsigned int *)x->args[i]));
|
95
101
|
break;
|
96
102
|
case TYPE_VOIDP:
|
@@ -101,19 +107,19 @@ with_gvl_callback(void *ptr)
|
|
101
107
|
case TYPE_LONG:
|
102
108
|
rb_ary_push(params, LONG2NUM(*(long *)x->args[i]));
|
103
109
|
break;
|
104
|
-
case
|
110
|
+
case TYPE_ULONG:
|
105
111
|
rb_ary_push(params, ULONG2NUM(*(unsigned long *)x->args[i]));
|
106
112
|
break;
|
107
113
|
case TYPE_CHAR:
|
108
114
|
rb_ary_push(params, INT2NUM(*(signed char *)x->args[i]));
|
109
115
|
break;
|
110
|
-
case
|
116
|
+
case TYPE_UCHAR:
|
111
117
|
rb_ary_push(params, UINT2NUM(*(unsigned char *)x->args[i]));
|
112
118
|
break;
|
113
119
|
case TYPE_SHORT:
|
114
120
|
rb_ary_push(params, INT2NUM(*(signed short *)x->args[i]));
|
115
121
|
break;
|
116
|
-
case
|
122
|
+
case TYPE_USHORT:
|
117
123
|
rb_ary_push(params, UINT2NUM(*(unsigned short *)x->args[i]));
|
118
124
|
break;
|
119
125
|
case TYPE_DOUBLE:
|
@@ -126,7 +132,7 @@ with_gvl_callback(void *ptr)
|
|
126
132
|
case TYPE_LONG_LONG:
|
127
133
|
rb_ary_push(params, LL2NUM(*(LONG_LONG *)x->args[i]));
|
128
134
|
break;
|
129
|
-
case
|
135
|
+
case TYPE_ULONG_LONG:
|
130
136
|
rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)x->args[i]));
|
131
137
|
break;
|
132
138
|
#endif
|
@@ -134,6 +140,20 @@ with_gvl_callback(void *ptr)
|
|
134
140
|
rb_ary_push(params,
|
135
141
|
rb_str_new_cstr(*((const char **)(x->args[i]))));
|
136
142
|
break;
|
143
|
+
case TYPE_BOOL:
|
144
|
+
if (sizeof(bool) == sizeof(char)) {
|
145
|
+
rb_ary_push(params, CBOOL2RBBOOL(*(unsigned char *)x->args[i]));
|
146
|
+
} else if (sizeof(bool) == sizeof(short)) {
|
147
|
+
rb_ary_push(params, CBOOL2RBBOOL(*(unsigned short *)x->args[i]));
|
148
|
+
} else if (sizeof(bool) == sizeof(int)) {
|
149
|
+
rb_ary_push(params, CBOOL2RBBOOL(*(unsigned int *)x->args[i]));
|
150
|
+
} else if (sizeof(bool) == sizeof(long)) {
|
151
|
+
rb_ary_push(params, CBOOL2RBBOOL(*(unsigned long *)x->args[i]));
|
152
|
+
} else {
|
153
|
+
rb_raise(rb_eNotImpError, "bool isn't supported: %u",
|
154
|
+
(unsigned int)sizeof(bool));
|
155
|
+
}
|
156
|
+
break;
|
137
157
|
default:
|
138
158
|
rb_raise(rb_eRuntimeError, "closure args: %d", type);
|
139
159
|
}
|
@@ -149,7 +169,7 @@ with_gvl_callback(void *ptr)
|
|
149
169
|
case TYPE_LONG:
|
150
170
|
*(long *)x->resp = NUM2LONG(ret);
|
151
171
|
break;
|
152
|
-
case
|
172
|
+
case TYPE_ULONG:
|
153
173
|
*(unsigned long *)x->resp = NUM2ULONG(ret);
|
154
174
|
break;
|
155
175
|
case TYPE_CHAR:
|
@@ -157,9 +177,9 @@ with_gvl_callback(void *ptr)
|
|
157
177
|
case TYPE_INT:
|
158
178
|
*(ffi_sarg *)x->resp = NUM2INT(ret);
|
159
179
|
break;
|
160
|
-
case
|
161
|
-
case
|
162
|
-
case
|
180
|
+
case TYPE_UCHAR:
|
181
|
+
case TYPE_USHORT:
|
182
|
+
case TYPE_UINT:
|
163
183
|
*(ffi_arg *)x->resp = NUM2UINT(ret);
|
164
184
|
break;
|
165
185
|
case TYPE_VOIDP:
|
@@ -175,7 +195,7 @@ with_gvl_callback(void *ptr)
|
|
175
195
|
case TYPE_LONG_LONG:
|
176
196
|
*(LONG_LONG *)x->resp = NUM2LL(ret);
|
177
197
|
break;
|
178
|
-
case
|
198
|
+
case TYPE_ULONG_LONG:
|
179
199
|
*(unsigned LONG_LONG *)x->resp = NUM2ULL(ret);
|
180
200
|
break;
|
181
201
|
#endif
|
@@ -183,6 +203,13 @@ with_gvl_callback(void *ptr)
|
|
183
203
|
/* Dangerous. Callback must keep reference of the String. */
|
184
204
|
*((const char **)(x->resp)) = StringValueCStr(ret);
|
185
205
|
break;
|
206
|
+
case TYPE_BOOL:
|
207
|
+
if (sizeof(bool) == sizeof(long)) {
|
208
|
+
*(unsigned long *)x->resp = RB_TEST(ret);
|
209
|
+
} else {
|
210
|
+
*(ffi_arg *)x->resp = RB_TEST(ret);
|
211
|
+
}
|
212
|
+
break;
|
186
213
|
default:
|
187
214
|
rb_raise(rb_eRuntimeError, "closure retval: %d", type);
|
188
215
|
}
|
@@ -224,9 +251,27 @@ allocate(VALUE klass)
|
|
224
251
|
return i;
|
225
252
|
}
|
226
253
|
|
254
|
+
static fiddle_closure *
|
255
|
+
get_raw(VALUE self)
|
256
|
+
{
|
257
|
+
fiddle_closure *closure;
|
258
|
+
TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
|
259
|
+
if (!closure) {
|
260
|
+
rb_raise(rb_eArgError, "already freed: %+"PRIsVALUE, self);
|
261
|
+
}
|
262
|
+
return closure;
|
263
|
+
}
|
264
|
+
|
265
|
+
typedef struct {
|
266
|
+
VALUE self;
|
267
|
+
int argc;
|
268
|
+
VALUE *argv;
|
269
|
+
} initialize_data;
|
270
|
+
|
227
271
|
static VALUE
|
228
|
-
|
272
|
+
initialize_body(VALUE user_data)
|
229
273
|
{
|
274
|
+
initialize_data *data = (initialize_data *)user_data;
|
230
275
|
VALUE ret;
|
231
276
|
VALUE args;
|
232
277
|
VALUE normalized_args;
|
@@ -237,14 +282,14 @@ initialize(int rbargc, VALUE argv[], VALUE self)
|
|
237
282
|
ffi_status result;
|
238
283
|
int i, argc;
|
239
284
|
|
240
|
-
if (2 == rb_scan_args(
|
241
|
-
|
285
|
+
if (2 == rb_scan_args(data->argc, data->argv, "21", &ret, &args, &abi))
|
286
|
+
abi = INT2NUM(FFI_DEFAULT_ABI);
|
242
287
|
|
243
288
|
Check_Type(args, T_ARRAY);
|
244
289
|
|
245
290
|
argc = RARRAY_LENINT(args);
|
246
291
|
|
247
|
-
TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
|
292
|
+
TypedData_Get_Struct(data->self, fiddle_closure, &closure_data_type, cl);
|
248
293
|
|
249
294
|
cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
|
250
295
|
|
@@ -257,8 +302,8 @@ initialize(int rbargc, VALUE argv[], VALUE self)
|
|
257
302
|
cl->argv[argc] = NULL;
|
258
303
|
|
259
304
|
ret = rb_fiddle_type_ensure(ret);
|
260
|
-
rb_iv_set(self, "@ctype", ret);
|
261
|
-
rb_iv_set(self, "@args", normalized_args);
|
305
|
+
rb_iv_set(data->self, "@ctype", ret);
|
306
|
+
rb_iv_set(data->self, "@args", normalized_args);
|
262
307
|
|
263
308
|
cif = &cl->cif;
|
264
309
|
pcl = cl->pcl;
|
@@ -269,38 +314,75 @@ initialize(int rbargc, VALUE argv[], VALUE self)
|
|
269
314
|
rb_fiddle_int_to_ffi_type(NUM2INT(ret)),
|
270
315
|
cl->argv);
|
271
316
|
|
272
|
-
if (FFI_OK != result)
|
273
|
-
|
317
|
+
if (FFI_OK != result) {
|
318
|
+
rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
|
319
|
+
}
|
274
320
|
|
275
321
|
#if USE_FFI_CLOSURE_ALLOC
|
276
322
|
result = ffi_prep_closure_loc(pcl, cif, callback,
|
277
|
-
|
323
|
+
(void *)(data->self), cl->code);
|
278
324
|
#else
|
279
|
-
result = ffi_prep_closure(pcl, cif, callback, (void *)self);
|
325
|
+
result = ffi_prep_closure(pcl, cif, callback, (void *)(data->self));
|
280
326
|
cl->code = (void *)pcl;
|
281
327
|
i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC);
|
282
328
|
if (i) {
|
283
|
-
|
329
|
+
rb_sys_fail("mprotect");
|
284
330
|
}
|
285
331
|
#endif
|
286
332
|
|
287
|
-
if (FFI_OK != result)
|
288
|
-
|
333
|
+
if (FFI_OK != result) {
|
334
|
+
rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
|
335
|
+
}
|
289
336
|
|
290
|
-
return self;
|
337
|
+
return data->self;
|
291
338
|
}
|
292
339
|
|
293
340
|
static VALUE
|
294
|
-
|
341
|
+
initialize_rescue(VALUE user_data, VALUE exception)
|
295
342
|
{
|
296
|
-
|
297
|
-
|
343
|
+
initialize_data *data = (initialize_data *)user_data;
|
344
|
+
dealloc(RTYPEDDATA_DATA(data->self));
|
345
|
+
RTYPEDDATA_DATA(data->self) = NULL;
|
346
|
+
rb_exc_raise(exception);
|
347
|
+
return data->self;
|
348
|
+
}
|
349
|
+
|
350
|
+
static VALUE
|
351
|
+
initialize(int argc, VALUE *argv, VALUE self)
|
352
|
+
{
|
353
|
+
initialize_data data;
|
354
|
+
data.self = self;
|
355
|
+
data.argc = argc;
|
356
|
+
data.argv = argv;
|
357
|
+
return rb_rescue(initialize_body, (VALUE)&data,
|
358
|
+
initialize_rescue, (VALUE)&data);
|
359
|
+
}
|
298
360
|
|
299
|
-
|
361
|
+
static VALUE
|
362
|
+
to_i(VALUE self)
|
363
|
+
{
|
364
|
+
fiddle_closure *closure = get_raw(self);
|
365
|
+
return PTR2NUM(closure->code);
|
366
|
+
}
|
300
367
|
|
301
|
-
|
368
|
+
static VALUE
|
369
|
+
closure_free(VALUE self)
|
370
|
+
{
|
371
|
+
fiddle_closure *closure;
|
372
|
+
TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
|
373
|
+
if (closure) {
|
374
|
+
dealloc(closure);
|
375
|
+
RTYPEDDATA_DATA(self) = NULL;
|
376
|
+
}
|
377
|
+
return RUBY_Qnil;
|
378
|
+
}
|
302
379
|
|
303
|
-
|
380
|
+
static VALUE
|
381
|
+
closure_freed_p(VALUE self)
|
382
|
+
{
|
383
|
+
fiddle_closure *closure;
|
384
|
+
TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
|
385
|
+
return closure ? RUBY_Qfalse : RUBY_Qtrue;
|
304
386
|
}
|
305
387
|
|
306
388
|
void
|
@@ -353,8 +435,24 @@ Init_fiddle_closure(void)
|
|
353
435
|
/*
|
354
436
|
* Document-method: to_i
|
355
437
|
*
|
356
|
-
* Returns the memory address for this closure
|
438
|
+
* Returns the memory address for this closure.
|
357
439
|
*/
|
358
440
|
rb_define_method(cFiddleClosure, "to_i", to_i, 0);
|
441
|
+
|
442
|
+
/*
|
443
|
+
* Document-method: free
|
444
|
+
*
|
445
|
+
* Free this closure explicitly. You can't use this closure anymore.
|
446
|
+
*
|
447
|
+
* If this closure is already freed, this does nothing.
|
448
|
+
*/
|
449
|
+
rb_define_method(cFiddleClosure, "free", closure_free, 0);
|
450
|
+
|
451
|
+
/*
|
452
|
+
* Document-method: freed?
|
453
|
+
*
|
454
|
+
* Whether this closure was freed explicitly.
|
455
|
+
*/
|
456
|
+
rb_define_method(cFiddleClosure, "freed?", closure_freed_p, 0);
|
359
457
|
}
|
360
458
|
/* vim: set noet sw=4 sts=4 */
|
data/ext/fiddle/conversions.c
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#include <stdbool.h>
|
2
|
+
|
1
3
|
#include <fiddle.h>
|
2
4
|
|
3
5
|
VALUE
|
@@ -44,6 +46,7 @@ rb_fiddle_type_ensure(VALUE type)
|
|
44
46
|
ID ptrdiff_t_id;
|
45
47
|
ID intptr_t_id;
|
46
48
|
ID uintptr_t_id;
|
49
|
+
ID bool_id;
|
47
50
|
RUBY_CONST_ID(void_id, "void");
|
48
51
|
RUBY_CONST_ID(voidp_id, "voidp");
|
49
52
|
RUBY_CONST_ID(char_id, "char");
|
@@ -74,6 +77,7 @@ rb_fiddle_type_ensure(VALUE type)
|
|
74
77
|
RUBY_CONST_ID(ptrdiff_t_id, "ptrdiff_t");
|
75
78
|
RUBY_CONST_ID(intptr_t_id, "intptr_t");
|
76
79
|
RUBY_CONST_ID(uintptr_t_id, "uintptr_t");
|
80
|
+
RUBY_CONST_ID(bool_id, "bool");
|
77
81
|
if (type_id == void_id) {
|
78
82
|
return INT2NUM(TYPE_VOID);
|
79
83
|
}
|
@@ -144,6 +148,9 @@ rb_fiddle_type_ensure(VALUE type)
|
|
144
148
|
else if (type_id == uintptr_t_id) {
|
145
149
|
return INT2NUM(TYPE_UINTPTR_T);
|
146
150
|
}
|
151
|
+
else if (type_id == bool_id) {
|
152
|
+
return INT2NUM(TYPE_BOOL);
|
153
|
+
}
|
147
154
|
else {
|
148
155
|
type = original_type;
|
149
156
|
}
|
@@ -187,6 +194,20 @@ rb_fiddle_int_to_ffi_type(int type)
|
|
187
194
|
return &ffi_type_double;
|
188
195
|
case TYPE_CONST_STRING:
|
189
196
|
return &ffi_type_pointer;
|
197
|
+
case TYPE_BOOL:
|
198
|
+
signed_p = 0;
|
199
|
+
if (sizeof(bool) == sizeof(char)) {
|
200
|
+
return rb_ffi_type_of(char);
|
201
|
+
} else if (sizeof(bool) == sizeof(short)) {
|
202
|
+
return rb_ffi_type_of(short);
|
203
|
+
} else if (sizeof(bool) == sizeof(int)) {
|
204
|
+
return rb_ffi_type_of(int);
|
205
|
+
} else if (sizeof(bool) == sizeof(long)) {
|
206
|
+
return rb_ffi_type_of(long);
|
207
|
+
} else {
|
208
|
+
rb_raise(rb_eNotImpError, "bool isn't supported: %u",
|
209
|
+
(unsigned int)sizeof(bool));
|
210
|
+
}
|
190
211
|
default:
|
191
212
|
rb_raise(rb_eRuntimeError, "unknown type %d", type);
|
192
213
|
}
|
@@ -209,34 +230,38 @@ rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst)
|
|
209
230
|
dst->pointer = NUM2PTR(rb_Integer(*src));
|
210
231
|
break;
|
211
232
|
case TYPE_CHAR:
|
212
|
-
|
233
|
+
if (RB_TYPE_P(*src, RUBY_T_STRING) && RSTRING_LEN(*src) == 1) {
|
234
|
+
dst->schar = RSTRING_PTR(*src)[0];
|
235
|
+
} else {
|
236
|
+
dst->schar = (signed char)NUM2INT(*src);
|
237
|
+
}
|
213
238
|
break;
|
214
|
-
case
|
239
|
+
case TYPE_UCHAR:
|
215
240
|
dst->uchar = (unsigned char)NUM2UINT(*src);
|
216
241
|
break;
|
217
242
|
case TYPE_SHORT:
|
218
243
|
dst->sshort = (unsigned short)NUM2INT(*src);
|
219
244
|
break;
|
220
|
-
case
|
245
|
+
case TYPE_USHORT:
|
221
246
|
dst->sshort = (signed short)NUM2UINT(*src);
|
222
247
|
break;
|
223
248
|
case TYPE_INT:
|
224
249
|
dst->sint = NUM2INT(*src);
|
225
250
|
break;
|
226
|
-
case
|
251
|
+
case TYPE_UINT:
|
227
252
|
dst->uint = NUM2UINT(*src);
|
228
253
|
break;
|
229
254
|
case TYPE_LONG:
|
230
255
|
dst->slong = NUM2LONG(*src);
|
231
256
|
break;
|
232
|
-
case
|
257
|
+
case TYPE_ULONG:
|
233
258
|
dst->ulong = NUM2ULONG(*src);
|
234
259
|
break;
|
235
260
|
#if HAVE_LONG_LONG
|
236
261
|
case TYPE_LONG_LONG:
|
237
262
|
dst->slong_long = NUM2LL(*src);
|
238
263
|
break;
|
239
|
-
case
|
264
|
+
case TYPE_ULONG_LONG:
|
240
265
|
dst->ulong_long = NUM2ULL(*src);
|
241
266
|
break;
|
242
267
|
#endif
|
@@ -254,8 +279,23 @@ rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst)
|
|
254
279
|
dst->pointer = rb_string_value_cstr(src);
|
255
280
|
}
|
256
281
|
break;
|
282
|
+
case TYPE_BOOL:
|
283
|
+
if (sizeof(bool) == sizeof(char)) {
|
284
|
+
dst->uchar = RB_TEST(*src);
|
285
|
+
} else if (sizeof(bool) == sizeof(short)) {
|
286
|
+
dst->ushort = RB_TEST(*src);
|
287
|
+
} else if (sizeof(bool) == sizeof(int)) {
|
288
|
+
dst->uint = RB_TEST(*src);
|
289
|
+
} else if (sizeof(bool) == sizeof(long)) {
|
290
|
+
dst->ulong = RB_TEST(*src);
|
291
|
+
} else {
|
292
|
+
rb_raise(rb_eNotImpError, "bool isn't supported: %u",
|
293
|
+
(unsigned int)sizeof(bool));
|
294
|
+
}
|
295
|
+
break;
|
257
296
|
default:
|
258
297
|
rb_raise(rb_eRuntimeError, "unknown type %d", type);
|
298
|
+
break;
|
259
299
|
}
|
260
300
|
}
|
261
301
|
|
@@ -283,24 +323,24 @@ rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval)
|
|
283
323
|
PTR2NUM((void *)retval.pointer));
|
284
324
|
case TYPE_CHAR:
|
285
325
|
return INT2NUM((signed char)retval.fffi_sarg);
|
286
|
-
case
|
326
|
+
case TYPE_UCHAR:
|
287
327
|
return INT2NUM((unsigned char)retval.fffi_arg);
|
288
328
|
case TYPE_SHORT:
|
289
329
|
return INT2NUM((signed short)retval.fffi_sarg);
|
290
|
-
case
|
330
|
+
case TYPE_USHORT:
|
291
331
|
return INT2NUM((unsigned short)retval.fffi_arg);
|
292
332
|
case TYPE_INT:
|
293
333
|
return INT2NUM((signed int)retval.fffi_sarg);
|
294
|
-
case
|
334
|
+
case TYPE_UINT:
|
295
335
|
return UINT2NUM((unsigned int)retval.fffi_arg);
|
296
336
|
case TYPE_LONG:
|
297
337
|
return LONG2NUM(retval.slong);
|
298
|
-
case
|
338
|
+
case TYPE_ULONG:
|
299
339
|
return ULONG2NUM(retval.ulong);
|
300
340
|
#if HAVE_LONG_LONG
|
301
341
|
case TYPE_LONG_LONG:
|
302
342
|
return LL2NUM(retval.slong_long);
|
303
|
-
case
|
343
|
+
case TYPE_ULONG_LONG:
|
304
344
|
return ULL2NUM(retval.ulong_long);
|
305
345
|
#endif
|
306
346
|
case TYPE_FLOAT:
|
@@ -314,6 +354,19 @@ rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval)
|
|
314
354
|
else {
|
315
355
|
return Qnil;
|
316
356
|
}
|
357
|
+
case TYPE_BOOL:
|
358
|
+
if (sizeof(bool) == sizeof(char)) {
|
359
|
+
return CBOOL2RBBOOL((unsigned char)retval.fffi_arg);
|
360
|
+
} else if (sizeof(bool) == sizeof(short)) {
|
361
|
+
return CBOOL2RBBOOL((unsigned short)retval.fffi_arg);
|
362
|
+
} else if (sizeof(bool) == sizeof(int)) {
|
363
|
+
return CBOOL2RBBOOL((unsigned int)retval.fffi_arg);
|
364
|
+
} else if (sizeof(bool) == sizeof(long)) {
|
365
|
+
return CBOOL2RBBOOL(retval.ulong);
|
366
|
+
} else {
|
367
|
+
rb_raise(rb_eNotImpError, "bool isn't supported: %u",
|
368
|
+
(unsigned int)sizeof(bool));
|
369
|
+
}
|
317
370
|
default:
|
318
371
|
rb_raise(rb_eRuntimeError, "unknown type %d", type);
|
319
372
|
}
|
data/ext/fiddle/conversions.h
CHANGED
data/ext/fiddle/extconf.rb
CHANGED
@@ -46,7 +46,7 @@ end
|
|
46
46
|
|
47
47
|
libffi_version = nil
|
48
48
|
have_libffi = false
|
49
|
-
bundle =
|
49
|
+
bundle = with_config("libffi-source-dir")
|
50
50
|
unless bundle
|
51
51
|
dir_config 'libffi'
|
52
52
|
|
@@ -63,31 +63,20 @@ unless bundle
|
|
63
63
|
end
|
64
64
|
if have_ffi_header && (have_library('ffi') || have_library('libffi'))
|
65
65
|
have_libffi = true
|
66
|
+
checking_for("undefined FFI_GO_CLOSURES is used") do
|
67
|
+
if egrep_cpp(/warning: 'FFI_GO_CLOSURES' is not defined/, cpp_include(ffi_header), "2>&1")
|
68
|
+
$defs.push('-DFFI_GO_CLOSURES=0')
|
69
|
+
end
|
70
|
+
end
|
66
71
|
end
|
67
72
|
end
|
68
73
|
|
69
74
|
unless have_libffi
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
require_relative "../../bin/extlibs"
|
75
|
-
extlibs = ExtLibs.new
|
76
|
-
cache_dir = File.expand_path("../../tmp/.download_cache", $srcdir)
|
77
|
-
ext_dir = File.expand_path("../../ext", $srcdir)
|
78
|
-
Dir.glob("#{$srcdir}/libffi-*/").each{|dir| FileUtils.rm_rf(dir)}
|
79
|
-
extlibs.run(["--cache=#{cache_dir}", ext_dir])
|
80
|
-
end
|
81
|
-
if bundle != false
|
82
|
-
libffi_package_name = Dir.glob("#{$srcdir}/libffi-*/")
|
83
|
-
.map {|n| File.basename(n)}
|
84
|
-
.max_by {|n| n.scan(/\d+/).map(&:to_i)}
|
85
|
-
end
|
86
|
-
unless libffi_package_name
|
87
|
-
raise "missing libffi. Please install libffi."
|
75
|
+
if bundle
|
76
|
+
libffi_srcdir = libffi_package_name = bundle
|
77
|
+
else
|
78
|
+
raise "missing libffi. Please install libffi or use --with-libffi-source-dir with libffi source location."
|
88
79
|
end
|
89
|
-
|
90
|
-
libffi_srcdir = "#{$srcdir}/#{libffi_package_name}"
|
91
80
|
ffi_header = 'ffi.h'
|
92
81
|
libffi = Struct.new(*%I[dir srcdir builddir include lib a cflags ldflags opt arch]).new
|
93
82
|
libffi.dir = libffi_package_name
|
@@ -187,6 +176,7 @@ else
|
|
187
176
|
end
|
188
177
|
|
189
178
|
have_header 'sys/mman.h'
|
179
|
+
have_header 'link.h'
|
190
180
|
|
191
181
|
if have_header "dlfcn.h"
|
192
182
|
have_library "dl"
|
@@ -196,8 +186,10 @@ if have_header "dlfcn.h"
|
|
196
186
|
end
|
197
187
|
|
198
188
|
have_func "dlerror"
|
189
|
+
have_func "dlinfo"
|
190
|
+
have_const("RTLD_DI_LINKMAP", "dlfcn.h")
|
199
191
|
elsif have_header "windows.h"
|
200
|
-
%w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
|
192
|
+
%w{ LoadLibrary FreeLibrary GetProcAddress GetModuleFileName }.each do |func|
|
201
193
|
abort "missing function #{func}" unless have_func(func)
|
202
194
|
end
|
203
195
|
|
@@ -222,12 +214,8 @@ types.each do |type, signed|
|
|
222
214
|
end
|
223
215
|
end
|
224
216
|
|
225
|
-
if have_header("ruby/memory_view.h")
|
226
|
-
have_type("rb_memory_view_t", ["ruby/memory_view.h"])
|
227
|
-
end
|
228
|
-
|
229
217
|
if libffi
|
230
|
-
$LOCAL_LIBS.prepend("
|
218
|
+
$LOCAL_LIBS.prepend("#{libffi.a} ").strip! # to exts.mk
|
231
219
|
$INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)')
|
232
220
|
end
|
233
221
|
create_makefile 'fiddle' do |conf|
|