fiddle 1.0.9 → 1.1.2
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/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
|
-
[](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|
|