fiddle 1.0.0 → 1.0.5
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 +52 -1
- data/Rakefile +4 -5
- data/bin/downloader.rb +331 -0
- data/bin/extlibs.rb +262 -0
- data/ext/fiddle/closure.c +5 -4
- data/ext/fiddle/conversions.c +205 -16
- data/ext/fiddle/conversions.h +14 -4
- data/ext/fiddle/depend +85 -0
- data/ext/fiddle/extconf.rb +62 -29
- data/ext/fiddle/extlibs +10 -2
- data/ext/fiddle/fiddle.c +133 -34
- data/ext/fiddle/fiddle.h +96 -32
- data/ext/fiddle/function.c +261 -93
- data/ext/fiddle/handle.c +10 -12
- data/ext/fiddle/memory_view.c +254 -0
- data/ext/fiddle/pinned.c +123 -0
- data/ext/fiddle/pointer.c +147 -24
- data/ext/fiddle/win32/fficonfig.h +0 -0
- data/ext/fiddle/win32/libffi-config.rb +1 -1
- data/ext/fiddle/win32/libffi.mk.tmpl +0 -0
- data/fiddle.gemspec +48 -5
- data/lib/fiddle.rb +3 -1
- data/lib/fiddle/cparser.rb +90 -25
- data/lib/fiddle/function.rb +5 -0
- data/lib/fiddle/import.rb +11 -9
- data/lib/fiddle/pack.rb +14 -7
- data/lib/fiddle/struct.rb +267 -43
- data/lib/fiddle/value.rb +18 -9
- data/lib/fiddle/version.rb +3 -0
- metadata +15 -12
- data/.gitignore +0 -13
- data/.travis.yml +0 -7
- data/Gemfile +0 -4
- data/bin/console +0 -14
- data/bin/setup +0 -8
data/ext/fiddle/pointer.c
CHANGED
@@ -2,8 +2,14 @@
|
|
2
2
|
* $Id$
|
3
3
|
*/
|
4
4
|
|
5
|
+
#include <stdbool.h>
|
5
6
|
#include <ruby/ruby.h>
|
6
7
|
#include <ruby/io.h>
|
8
|
+
|
9
|
+
#ifdef HAVE_RUBY_MEMORY_VIEW_H
|
10
|
+
# include <ruby/memory_view.h>
|
11
|
+
#endif
|
12
|
+
|
7
13
|
#include <ctype.h>
|
8
14
|
#include <fiddle.h>
|
9
15
|
|
@@ -24,6 +30,7 @@ struct ptr_data {
|
|
24
30
|
void *ptr;
|
25
31
|
long size;
|
26
32
|
freefunc_t free;
|
33
|
+
bool freed;
|
27
34
|
VALUE wrap[2];
|
28
35
|
};
|
29
36
|
|
@@ -57,14 +64,19 @@ fiddle_ptr_mark(void *ptr)
|
|
57
64
|
}
|
58
65
|
|
59
66
|
static void
|
60
|
-
|
67
|
+
fiddle_ptr_free_ptr(void *ptr)
|
61
68
|
{
|
62
69
|
struct ptr_data *data = ptr;
|
63
|
-
if (data->ptr) {
|
64
|
-
|
65
|
-
|
66
|
-
}
|
70
|
+
if (data->ptr && data->free && !data->freed) {
|
71
|
+
data->freed = true;
|
72
|
+
(*(data->free))(data->ptr);
|
67
73
|
}
|
74
|
+
}
|
75
|
+
|
76
|
+
static void
|
77
|
+
fiddle_ptr_free(void *ptr)
|
78
|
+
{
|
79
|
+
fiddle_ptr_free_ptr(ptr);
|
68
80
|
xfree(ptr);
|
69
81
|
}
|
70
82
|
|
@@ -80,6 +92,38 @@ static const rb_data_type_t fiddle_ptr_data_type = {
|
|
80
92
|
{fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,},
|
81
93
|
};
|
82
94
|
|
95
|
+
#ifdef FIDDLE_MEMORY_VIEW
|
96
|
+
static struct ptr_data *
|
97
|
+
fiddle_ptr_check_memory_view(VALUE obj)
|
98
|
+
{
|
99
|
+
struct ptr_data *data;
|
100
|
+
TypedData_Get_Struct(obj, struct ptr_data, &fiddle_ptr_data_type, data);
|
101
|
+
if (data->ptr == NULL || data->size == 0) return NULL;
|
102
|
+
return data;
|
103
|
+
}
|
104
|
+
|
105
|
+
static int
|
106
|
+
fiddle_ptr_memory_view_available_p(VALUE obj)
|
107
|
+
{
|
108
|
+
return fiddle_ptr_check_memory_view(obj) != NULL;
|
109
|
+
}
|
110
|
+
|
111
|
+
static int
|
112
|
+
fiddle_ptr_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
|
113
|
+
{
|
114
|
+
struct ptr_data *data = fiddle_ptr_check_memory_view(obj);
|
115
|
+
rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, true);
|
116
|
+
|
117
|
+
return 1;
|
118
|
+
}
|
119
|
+
|
120
|
+
static const rb_memory_view_entry_t fiddle_ptr_memory_view_entry = {
|
121
|
+
fiddle_ptr_get_memory_view,
|
122
|
+
NULL,
|
123
|
+
fiddle_ptr_memory_view_available_p
|
124
|
+
};
|
125
|
+
#endif
|
126
|
+
|
83
127
|
static VALUE
|
84
128
|
rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
|
85
129
|
{
|
@@ -89,8 +133,8 @@ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
|
|
89
133
|
val = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data);
|
90
134
|
data->ptr = ptr;
|
91
135
|
data->free = func;
|
136
|
+
data->freed = false;
|
92
137
|
data->size = size;
|
93
|
-
OBJ_TAINT(val);
|
94
138
|
|
95
139
|
return val;
|
96
140
|
}
|
@@ -102,13 +146,13 @@ rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func)
|
|
102
146
|
}
|
103
147
|
|
104
148
|
static VALUE
|
105
|
-
rb_fiddle_ptr_malloc(long size, freefunc_t func)
|
149
|
+
rb_fiddle_ptr_malloc(VALUE klass, long size, freefunc_t func)
|
106
150
|
{
|
107
151
|
void *ptr;
|
108
152
|
|
109
153
|
ptr = ruby_xmalloc((size_t)size);
|
110
154
|
memset(ptr,0,(size_t)size);
|
111
|
-
return
|
155
|
+
return rb_fiddle_ptr_new2(klass, ptr, size, func);
|
112
156
|
}
|
113
157
|
|
114
158
|
static void *
|
@@ -141,6 +185,7 @@ rb_fiddle_ptr_s_allocate(VALUE klass)
|
|
141
185
|
data->ptr = 0;
|
142
186
|
data->size = 0;
|
143
187
|
data->free = 0;
|
188
|
+
data->freed = false;
|
144
189
|
|
145
190
|
return obj;
|
146
191
|
}
|
@@ -192,16 +237,53 @@ rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self)
|
|
192
237
|
return Qnil;
|
193
238
|
}
|
194
239
|
|
240
|
+
static VALUE
|
241
|
+
rb_fiddle_ptr_call_free(VALUE self);
|
242
|
+
|
195
243
|
/*
|
196
244
|
* call-seq:
|
197
|
-
*
|
198
245
|
* Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance
|
246
|
+
* Fiddle::Pointer.malloc(size, freefunc) { |pointer| ... } => ...
|
247
|
+
*
|
248
|
+
* == Examples
|
249
|
+
*
|
250
|
+
* # Automatically freeing the pointer when the block is exited - recommended
|
251
|
+
* Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) do |pointer|
|
252
|
+
* ...
|
253
|
+
* end
|
254
|
+
*
|
255
|
+
* # Manually freeing but relying on the garbage collector otherwise
|
256
|
+
* pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
|
257
|
+
* ...
|
258
|
+
* pointer.call_free
|
259
|
+
*
|
260
|
+
* # Relying on the garbage collector - may lead to unlimited memory allocated before freeing any, but safe
|
261
|
+
* pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
|
262
|
+
* ...
|
263
|
+
*
|
264
|
+
* # Only manually freeing
|
265
|
+
* pointer = Fiddle::Pointer.malloc(size)
|
266
|
+
* begin
|
267
|
+
* ...
|
268
|
+
* ensure
|
269
|
+
* Fiddle.free pointer
|
270
|
+
* end
|
271
|
+
*
|
272
|
+
* # No free function and no call to free - the native memory will leak if the pointer is garbage collected
|
273
|
+
* pointer = Fiddle::Pointer.malloc(size)
|
274
|
+
* ...
|
199
275
|
*
|
200
276
|
* Allocate +size+ bytes of memory and associate it with an optional
|
201
|
-
* +freefunc
|
277
|
+
* +freefunc+.
|
278
|
+
*
|
279
|
+
* If a block is supplied, the pointer will be yielded to the block instead of
|
280
|
+
* being returned, and the return value of the block will be returned. A
|
281
|
+
* +freefunc+ must be supplied if a block is.
|
202
282
|
*
|
203
|
-
* +freefunc+
|
204
|
-
*
|
283
|
+
* If a +freefunc+ is supplied it will be called once, when the pointer is
|
284
|
+
* garbage collected or when the block is left if a block is supplied or
|
285
|
+
* when the user calls +call_free+, whichever happens first. +freefunc+ must be
|
286
|
+
* an address pointing to a function or an instance of +Fiddle::Function+.
|
205
287
|
*/
|
206
288
|
static VALUE
|
207
289
|
rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
|
@@ -223,10 +305,17 @@ rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
|
|
223
305
|
rb_bug("rb_fiddle_ptr_s_malloc");
|
224
306
|
}
|
225
307
|
|
226
|
-
obj = rb_fiddle_ptr_malloc(s,f);
|
308
|
+
obj = rb_fiddle_ptr_malloc(klass, s,f);
|
227
309
|
if (wrap) RPTR_DATA(obj)->wrap[1] = wrap;
|
228
310
|
|
229
|
-
|
311
|
+
if (rb_block_given_p()) {
|
312
|
+
if (!f) {
|
313
|
+
rb_raise(rb_eArgError, "a free function must be supplied to Fiddle::Pointer.malloc when it is called with a block");
|
314
|
+
}
|
315
|
+
return rb_ensure(rb_yield, obj, rb_fiddle_ptr_call_free, obj);
|
316
|
+
} else {
|
317
|
+
return obj;
|
318
|
+
}
|
230
319
|
}
|
231
320
|
|
232
321
|
/*
|
@@ -351,6 +440,34 @@ rb_fiddle_ptr_free_get(VALUE self)
|
|
351
440
|
return rb_fiddle_new_function(address, arg_types, ret_type);
|
352
441
|
}
|
353
442
|
|
443
|
+
/*
|
444
|
+
* call-seq: call_free => nil
|
445
|
+
*
|
446
|
+
* Call the free function for this pointer. Calling more than once will do
|
447
|
+
* nothing. Does nothing if there is no free function attached.
|
448
|
+
*/
|
449
|
+
static VALUE
|
450
|
+
rb_fiddle_ptr_call_free(VALUE self)
|
451
|
+
{
|
452
|
+
struct ptr_data *pdata;
|
453
|
+
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
|
454
|
+
fiddle_ptr_free_ptr(pdata);
|
455
|
+
return Qnil;
|
456
|
+
}
|
457
|
+
|
458
|
+
/*
|
459
|
+
* call-seq: freed? => bool
|
460
|
+
*
|
461
|
+
* Returns if the free function for this pointer has been called.
|
462
|
+
*/
|
463
|
+
static VALUE
|
464
|
+
rb_fiddle_ptr_freed_p(VALUE self)
|
465
|
+
{
|
466
|
+
struct ptr_data *pdata;
|
467
|
+
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
|
468
|
+
return pdata->freed ? Qtrue : Qfalse;
|
469
|
+
}
|
470
|
+
|
354
471
|
/*
|
355
472
|
* call-seq:
|
356
473
|
*
|
@@ -376,11 +493,11 @@ rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self)
|
|
376
493
|
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
|
377
494
|
switch (rb_scan_args(argc, argv, "01", &arg1)) {
|
378
495
|
case 0:
|
379
|
-
val =
|
496
|
+
val = rb_str_new2((char*)(data->ptr));
|
380
497
|
break;
|
381
498
|
case 1:
|
382
499
|
len = NUM2INT(arg1);
|
383
|
-
val =
|
500
|
+
val = rb_str_new((char*)(data->ptr), len);
|
384
501
|
break;
|
385
502
|
default:
|
386
503
|
rb_bug("rb_fiddle_ptr_to_s");
|
@@ -414,11 +531,11 @@ rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self)
|
|
414
531
|
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
|
415
532
|
switch (rb_scan_args(argc, argv, "01", &arg1)) {
|
416
533
|
case 0:
|
417
|
-
val =
|
534
|
+
val = rb_str_new((char*)(data->ptr),data->size);
|
418
535
|
break;
|
419
536
|
case 1:
|
420
537
|
len = NUM2INT(arg1);
|
421
|
-
val =
|
538
|
+
val = rb_str_new((char*)(data->ptr), len);
|
422
539
|
break;
|
423
540
|
default:
|
424
541
|
rb_bug("rb_fiddle_ptr_to_str");
|
@@ -440,7 +557,7 @@ rb_fiddle_ptr_inspect(VALUE self)
|
|
440
557
|
|
441
558
|
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
|
442
559
|
return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>",
|
443
|
-
RB_OBJ_CLASSNAME(self), data, data->ptr, data->size, data->free);
|
560
|
+
RB_OBJ_CLASSNAME(self), (void *)data, data->ptr, data->size, (void *)data->free);
|
444
561
|
}
|
445
562
|
|
446
563
|
/*
|
@@ -542,7 +659,7 @@ rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
|
|
542
659
|
struct ptr_data *data;
|
543
660
|
|
544
661
|
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
|
545
|
-
if (!data->ptr) rb_raise(
|
662
|
+
if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
|
546
663
|
switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
|
547
664
|
case 1:
|
548
665
|
offset = NUM2ULONG(arg0);
|
@@ -551,7 +668,7 @@ rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
|
|
551
668
|
case 2:
|
552
669
|
offset = NUM2ULONG(arg0);
|
553
670
|
len = NUM2ULONG(arg1);
|
554
|
-
retval =
|
671
|
+
retval = rb_str_new((char *)data->ptr + offset, len);
|
555
672
|
break;
|
556
673
|
default:
|
557
674
|
rb_bug("rb_fiddle_ptr_aref()");
|
@@ -580,7 +697,7 @@ rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self)
|
|
580
697
|
struct ptr_data *data;
|
581
698
|
|
582
699
|
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
|
583
|
-
if (!data->ptr) rb_raise(
|
700
|
+
if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
|
584
701
|
switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
|
585
702
|
case 2:
|
586
703
|
offset = NUM2ULONG(arg0);
|
@@ -661,7 +778,7 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
|
|
661
778
|
wrap = 0;
|
662
779
|
}
|
663
780
|
else{
|
664
|
-
rb_raise(
|
781
|
+
rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object");
|
665
782
|
}
|
666
783
|
}
|
667
784
|
else{
|
@@ -669,7 +786,6 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
|
|
669
786
|
if (num == val) wrap = 0;
|
670
787
|
ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL);
|
671
788
|
}
|
672
|
-
OBJ_INFECT(ptr, val);
|
673
789
|
if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap;
|
674
790
|
return ptr;
|
675
791
|
}
|
@@ -677,6 +793,7 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
|
|
677
793
|
void
|
678
794
|
Init_fiddle_pointer(void)
|
679
795
|
{
|
796
|
+
#undef rb_intern
|
680
797
|
id_to_ptr = rb_intern("to_ptr");
|
681
798
|
|
682
799
|
/* Document-class: Fiddle::Pointer
|
@@ -692,6 +809,8 @@ Init_fiddle_pointer(void)
|
|
692
809
|
rb_define_method(rb_cPointer, "initialize", rb_fiddle_ptr_initialize, -1);
|
693
810
|
rb_define_method(rb_cPointer, "free=", rb_fiddle_ptr_free_set, 1);
|
694
811
|
rb_define_method(rb_cPointer, "free", rb_fiddle_ptr_free_get, 0);
|
812
|
+
rb_define_method(rb_cPointer, "call_free", rb_fiddle_ptr_call_free, 0);
|
813
|
+
rb_define_method(rb_cPointer, "freed?", rb_fiddle_ptr_freed_p, 0);
|
695
814
|
rb_define_method(rb_cPointer, "to_i", rb_fiddle_ptr_to_i, 0);
|
696
815
|
rb_define_method(rb_cPointer, "to_int", rb_fiddle_ptr_to_i, 0);
|
697
816
|
rb_define_method(rb_cPointer, "to_value", rb_fiddle_ptr_to_value, 0);
|
@@ -713,6 +832,10 @@ Init_fiddle_pointer(void)
|
|
713
832
|
rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0);
|
714
833
|
rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1);
|
715
834
|
|
835
|
+
#ifdef FIDDLE_MEMORY_VIEW
|
836
|
+
rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry);
|
837
|
+
#endif
|
838
|
+
|
716
839
|
/* Document-const: NULL
|
717
840
|
*
|
718
841
|
* A NULL pointer
|
File without changes
|
@@ -32,7 +32,7 @@ IO.foreach("#{srcdir}/configure.ac") do |line|
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
builddir = srcdir == "." ? enable['builddir'] : "."
|
35
|
+
builddir = srcdir == "." ? (enable['builddir'] || ".") : "."
|
36
36
|
conf['TARGET'] = /^x64/ =~ host ? "X86_WIN64" : "X86_WIN32"
|
37
37
|
|
38
38
|
FileUtils.mkdir_p([builddir, "#{builddir}/include", "#{builddir}/src/x86"])
|
File without changes
|
data/fiddle.gemspec
CHANGED
@@ -1,23 +1,66 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
version_module = Module.new do
|
4
|
+
version_rb = File.join(__dir__, "lib/fiddle/version.rb")
|
5
|
+
module_eval(File.read(version_rb), version_rb, __LINE__)
|
6
|
+
end
|
7
|
+
|
2
8
|
Gem::Specification.new do |spec|
|
3
9
|
spec.name = "fiddle"
|
4
|
-
spec.version =
|
10
|
+
spec.version = version_module::Fiddle::VERSION
|
5
11
|
spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"]
|
6
12
|
spec.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org"]
|
7
13
|
|
8
14
|
spec.summary = %q{A libffi wrapper for Ruby.}
|
9
15
|
spec.description = %q{A libffi wrapper for Ruby.}
|
10
16
|
spec.homepage = "https://github.com/ruby/fiddle"
|
11
|
-
spec.
|
17
|
+
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
12
18
|
|
13
|
-
spec.files = [
|
14
|
-
|
15
|
-
|
19
|
+
spec.files = [
|
20
|
+
"LICENSE.txt",
|
21
|
+
"README.md",
|
22
|
+
"Rakefile",
|
23
|
+
"bin/downloader.rb",
|
24
|
+
"bin/extlibs.rb",
|
25
|
+
"ext/fiddle/closure.c",
|
26
|
+
"ext/fiddle/closure.h",
|
27
|
+
"ext/fiddle/conversions.c",
|
28
|
+
"ext/fiddle/conversions.h",
|
29
|
+
"ext/fiddle/depend",
|
30
|
+
"ext/fiddle/extconf.rb",
|
31
|
+
"ext/fiddle/extlibs",
|
32
|
+
"ext/fiddle/fiddle.c",
|
33
|
+
"ext/fiddle/fiddle.h",
|
34
|
+
"ext/fiddle/function.c",
|
35
|
+
"ext/fiddle/function.h",
|
36
|
+
"ext/fiddle/handle.c",
|
37
|
+
"ext/fiddle/memory_view.c",
|
38
|
+
"ext/fiddle/pinned.c",
|
39
|
+
"ext/fiddle/pointer.c",
|
40
|
+
"ext/fiddle/win32/fficonfig.h",
|
41
|
+
"ext/fiddle/win32/libffi-3.2.1-mswin.patch",
|
42
|
+
"ext/fiddle/win32/libffi-config.rb",
|
43
|
+
"ext/fiddle/win32/libffi.mk.tmpl",
|
44
|
+
"fiddle.gemspec",
|
45
|
+
"lib/fiddle.rb",
|
46
|
+
"lib/fiddle/closure.rb",
|
47
|
+
"lib/fiddle/cparser.rb",
|
48
|
+
"lib/fiddle/function.rb",
|
49
|
+
"lib/fiddle/import.rb",
|
50
|
+
"lib/fiddle/pack.rb",
|
51
|
+
"lib/fiddle/struct.rb",
|
52
|
+
"lib/fiddle/types.rb",
|
53
|
+
"lib/fiddle/value.rb",
|
54
|
+
"lib/fiddle/version.rb",
|
55
|
+
]
|
16
56
|
spec.require_paths = ["lib"]
|
57
|
+
spec.extensions = ["ext/fiddle/extconf.rb"]
|
17
58
|
|
18
59
|
spec.required_ruby_version = ">= 2.3.0"
|
19
60
|
|
20
61
|
spec.add_development_dependency "bundler"
|
21
62
|
spec.add_development_dependency "rake"
|
22
63
|
spec.add_development_dependency "rake-compiler"
|
64
|
+
|
65
|
+
spec.metadata["msys2_mingw_dependencies"] = "libffi"
|
23
66
|
end
|
data/lib/fiddle.rb
CHANGED
data/lib/fiddle/cparser.rb
CHANGED
@@ -35,12 +35,37 @@ module Fiddle
|
|
35
35
|
def parse_struct_signature(signature, tymap=nil)
|
36
36
|
if signature.is_a?(String)
|
37
37
|
signature = split_arguments(signature, /[,;]/)
|
38
|
+
elsif signature.is_a?(Hash)
|
39
|
+
signature = [signature]
|
38
40
|
end
|
39
41
|
mems = []
|
40
42
|
tys = []
|
41
43
|
signature.each{|msig|
|
42
|
-
msig = compact(msig)
|
44
|
+
msig = compact(msig) if msig.is_a?(String)
|
43
45
|
case msig
|
46
|
+
when Hash
|
47
|
+
msig.each do |struct_name, struct_signature|
|
48
|
+
struct_name = struct_name.to_s if struct_name.is_a?(Symbol)
|
49
|
+
struct_name = compact(struct_name)
|
50
|
+
struct_count = nil
|
51
|
+
if struct_name =~ /^([\w\*\s]+)\[(\d+)\]$/
|
52
|
+
struct_count = $2.to_i
|
53
|
+
struct_name = $1
|
54
|
+
end
|
55
|
+
if struct_signature.respond_to?(:entity_class)
|
56
|
+
struct_type = struct_signature
|
57
|
+
else
|
58
|
+
parsed_struct = parse_struct_signature(struct_signature, tymap)
|
59
|
+
struct_type = CStructBuilder.create(CStruct, *parsed_struct)
|
60
|
+
end
|
61
|
+
if struct_count
|
62
|
+
ty = [struct_type, struct_count]
|
63
|
+
else
|
64
|
+
ty = struct_type
|
65
|
+
end
|
66
|
+
mems.push([struct_name, struct_type.members])
|
67
|
+
tys.push(ty)
|
68
|
+
end
|
44
69
|
when /^[\w\*\s]+[\*\s](\w+)$/
|
45
70
|
mems.push($1)
|
46
71
|
tys.push(parse_ctype(msig, tymap))
|
@@ -128,50 +153,90 @@ module Fiddle
|
|
128
153
|
return [parse_ctype(ty[0], tymap), ty[1]]
|
129
154
|
when 'void'
|
130
155
|
return TYPE_VOID
|
131
|
-
when
|
132
|
-
|
133
|
-
return TYPE_LONG_LONG
|
134
|
-
else
|
156
|
+
when /\A(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?\z/
|
157
|
+
unless Fiddle.const_defined?(:TYPE_LONG_LONG)
|
135
158
|
raise(RuntimeError, "unsupported type: #{ty}")
|
136
159
|
end
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
else
|
160
|
+
return TYPE_LONG_LONG
|
161
|
+
when /\A(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?\z/
|
162
|
+
unless Fiddle.const_defined?(:TYPE_LONG_LONG)
|
141
163
|
raise(RuntimeError, "unsupported type: #{ty}")
|
142
164
|
end
|
143
|
-
|
165
|
+
return -TYPE_LONG_LONG
|
166
|
+
when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/
|
144
167
|
return TYPE_LONG
|
145
|
-
when
|
168
|
+
when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/
|
146
169
|
return -TYPE_LONG
|
147
|
-
when
|
170
|
+
when /\A(?:signed\s+)?int(?:\s+\w+)?\z/
|
148
171
|
return TYPE_INT
|
149
|
-
when
|
172
|
+
when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/
|
150
173
|
return -TYPE_INT
|
151
|
-
when
|
174
|
+
when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/
|
152
175
|
return TYPE_SHORT
|
153
|
-
when
|
176
|
+
when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/
|
154
177
|
return -TYPE_SHORT
|
155
|
-
when
|
178
|
+
when /\A(?:signed\s+)?char(?:\s+\w+)?\z/
|
156
179
|
return TYPE_CHAR
|
157
|
-
when
|
180
|
+
when /\Aunsigned\s+char(?:\s+\w+)?\z/
|
158
181
|
return -TYPE_CHAR
|
159
|
-
when
|
182
|
+
when /\Aint8_t(?:\s+\w+)?\z/
|
183
|
+
unless Fiddle.const_defined?(:TYPE_INT8_T)
|
184
|
+
raise(RuntimeError, "unsupported type: #{ty}")
|
185
|
+
end
|
186
|
+
return TYPE_INT8_T
|
187
|
+
when /\Auint8_t(?:\s+\w+)?\z/
|
188
|
+
unless Fiddle.const_defined?(:TYPE_INT8_T)
|
189
|
+
raise(RuntimeError, "unsupported type: #{ty}")
|
190
|
+
end
|
191
|
+
return -TYPE_INT8_T
|
192
|
+
when /\Aint16_t(?:\s+\w+)?\z/
|
193
|
+
unless Fiddle.const_defined?(:TYPE_INT16_T)
|
194
|
+
raise(RuntimeError, "unsupported type: #{ty}")
|
195
|
+
end
|
196
|
+
return TYPE_INT16_T
|
197
|
+
when /\Auint16_t(?:\s+\w+)?\z/
|
198
|
+
unless Fiddle.const_defined?(:TYPE_INT16_T)
|
199
|
+
raise(RuntimeError, "unsupported type: #{ty}")
|
200
|
+
end
|
201
|
+
return -TYPE_INT16_T
|
202
|
+
when /\Aint32_t(?:\s+\w+)?\z/
|
203
|
+
unless Fiddle.const_defined?(:TYPE_INT32_T)
|
204
|
+
raise(RuntimeError, "unsupported type: #{ty}")
|
205
|
+
end
|
206
|
+
return TYPE_INT32_T
|
207
|
+
when /\Auint32_t(?:\s+\w+)?\z/
|
208
|
+
unless Fiddle.const_defined?(:TYPE_INT32_T)
|
209
|
+
raise(RuntimeError, "unsupported type: #{ty}")
|
210
|
+
end
|
211
|
+
return -TYPE_INT32_T
|
212
|
+
when /\Aint64_t(?:\s+\w+)?\z/
|
213
|
+
unless Fiddle.const_defined?(:TYPE_INT64_T)
|
214
|
+
raise(RuntimeError, "unsupported type: #{ty}")
|
215
|
+
end
|
216
|
+
return TYPE_INT64_T
|
217
|
+
when /\Auint64_t(?:\s+\w+)?\z/
|
218
|
+
unless Fiddle.const_defined?(:TYPE_INT64_T)
|
219
|
+
raise(RuntimeError, "unsupported type: #{ty}")
|
220
|
+
end
|
221
|
+
return -TYPE_INT64_T
|
222
|
+
when /\Afloat(?:\s+\w+)?\z/
|
160
223
|
return TYPE_FLOAT
|
161
|
-
when
|
224
|
+
when /\Adouble(?:\s+\w+)?\z/
|
162
225
|
return TYPE_DOUBLE
|
163
|
-
when
|
226
|
+
when /\Asize_t(?:\s+\w+)?\z/
|
164
227
|
return TYPE_SIZE_T
|
165
|
-
when
|
228
|
+
when /\Assize_t(?:\s+\w+)?\z/
|
166
229
|
return TYPE_SSIZE_T
|
167
|
-
when
|
230
|
+
when /\Aptrdiff_t(?:\s+\w+)?\z/
|
168
231
|
return TYPE_PTRDIFF_T
|
169
|
-
when
|
232
|
+
when /\Aintptr_t(?:\s+\w+)?\z/
|
170
233
|
return TYPE_INTPTR_T
|
171
|
-
when
|
234
|
+
when /\Auintptr_t(?:\s+\w+)?\z/
|
172
235
|
return TYPE_UINTPTR_T
|
173
236
|
when /\*/, /\[[\s\d]*\]/
|
174
237
|
return TYPE_VOIDP
|
238
|
+
when "..."
|
239
|
+
return TYPE_VARIADIC
|
175
240
|
else
|
176
241
|
ty = ty.split(' ', 2)[0]
|
177
242
|
if( tymap[ty] )
|
@@ -186,7 +251,7 @@ module Fiddle
|
|
186
251
|
|
187
252
|
def split_arguments(arguments, sep=',')
|
188
253
|
return [] if arguments.strip == 'void'
|
189
|
-
arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]
|
254
|
+
arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+|\.\.\.)(?:#{sep}\s*|\z)/).collect {|m| m[0]}
|
190
255
|
end
|
191
256
|
|
192
257
|
def compact(signature)
|