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.
@@ -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
- fiddle_ptr_free(void *ptr)
67
+ fiddle_ptr_free_ptr(void *ptr)
61
68
  {
62
69
  struct ptr_data *data = ptr;
63
- if (data->ptr) {
64
- if (data->free) {
65
- (*(data->free))(data->ptr);
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 rb_fiddle_ptr_new(ptr, size, func);
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+ that will be called when the pointer is garbage collected.
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+ must be an address pointing to a function or an instance of
204
- * Fiddle::Function
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
- return obj;
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 = rb_tainted_str_new2((char*)(data->ptr));
496
+ val = rb_str_new2((char*)(data->ptr));
380
497
  break;
381
498
  case 1:
382
499
  len = NUM2INT(arg1);
383
- val = rb_tainted_str_new((char*)(data->ptr), len);
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 = rb_tainted_str_new((char*)(data->ptr),data->size);
534
+ val = rb_str_new((char*)(data->ptr),data->size);
418
535
  break;
419
536
  case 1:
420
537
  len = NUM2INT(arg1);
421
- val = rb_tainted_str_new((char*)(data->ptr), len);
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(rb_eFiddleError, "NULL pointer dereference");
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 = rb_tainted_str_new((char *)data->ptr + offset, len);
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(rb_eFiddleError, "NULL pointer dereference");
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(rb_eFiddleError, "to_ptr should return a Fiddle::Pointer object");
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
@@ -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 = '1.0.0'
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.license = "BSD-2-Clause"
17
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
12
18
 
13
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "ext/fiddle/closure.c", "ext/fiddle/closure.h", "ext/fiddle/conversions.c", "ext/fiddle/conversions.h", "ext/fiddle/extconf.rb", "ext/fiddle/extlibs", "ext/fiddle/fiddle.c", "ext/fiddle/fiddle.h", "ext/fiddle/function.c", "ext/fiddle/function.h", "ext/fiddle/handle.c", "ext/fiddle/pointer.c", "ext/fiddle/win32/fficonfig.h", "ext/fiddle/win32/libffi-3.2.1-mswin.patch", "ext/fiddle/win32/libffi-config.rb", "ext/fiddle/win32/libffi.mk.tmpl", "fiddle.gemspec", "lib/fiddle.rb", "lib/fiddle/closure.rb", "lib/fiddle/cparser.rb", "lib/fiddle/function.rb", "lib/fiddle/import.rb", "lib/fiddle/pack.rb", "lib/fiddle/struct.rb", "lib/fiddle/types.rb", "lib/fiddle/value.rb"]
14
- spec.bindir = "exe"
15
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
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
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'fiddle.so'
3
- require 'fiddle/function'
4
4
  require 'fiddle/closure'
5
+ require 'fiddle/function'
6
+ require 'fiddle/version'
5
7
 
6
8
  module Fiddle
7
9
  if WINDOWS
@@ -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 /^(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?$/
132
- if( defined?(TYPE_LONG_LONG) )
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
- when /^(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?$/
138
- if( defined?(TYPE_LONG_LONG) )
139
- return -TYPE_LONG_LONG
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
- when /^(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?$/
165
+ return -TYPE_LONG_LONG
166
+ when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/
144
167
  return TYPE_LONG
145
- when /^unsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?$/
168
+ when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/
146
169
  return -TYPE_LONG
147
- when /^(?:signed\s+)?int(?:\s+\w+)?$/
170
+ when /\A(?:signed\s+)?int(?:\s+\w+)?\z/
148
171
  return TYPE_INT
149
- when /^(?:unsigned\s+int|uint)(?:\s+\w+)?$/
172
+ when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/
150
173
  return -TYPE_INT
151
- when /^(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?$/
174
+ when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/
152
175
  return TYPE_SHORT
153
- when /^unsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?$/
176
+ when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/
154
177
  return -TYPE_SHORT
155
- when /^(?:signed\s+)?char(?:\s+\w+)?$/
178
+ when /\A(?:signed\s+)?char(?:\s+\w+)?\z/
156
179
  return TYPE_CHAR
157
- when /^unsigned\s+char(?:\s+\w+)?$/
180
+ when /\Aunsigned\s+char(?:\s+\w+)?\z/
158
181
  return -TYPE_CHAR
159
- when /^float(?:\s+\w+)?$/
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 /^double(?:\s+\w+)?$/
224
+ when /\Adouble(?:\s+\w+)?\z/
162
225
  return TYPE_DOUBLE
163
- when /^size_t(?:\s+\w+)?$/
226
+ when /\Asize_t(?:\s+\w+)?\z/
164
227
  return TYPE_SIZE_T
165
- when /^ssize_t(?:\s+\w+)?$/
228
+ when /\Assize_t(?:\s+\w+)?\z/
166
229
  return TYPE_SSIZE_T
167
- when /^ptrdiff_t(?:\s+\w+)?$/
230
+ when /\Aptrdiff_t(?:\s+\w+)?\z/
168
231
  return TYPE_PTRDIFF_T
169
- when /^intptr_t(?:\s+\w+)?$/
232
+ when /\Aintptr_t(?:\s+\w+)?\z/
170
233
  return TYPE_INTPTR_T
171
- when /^uintptr_t(?:\s+\w+)?$/
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\[\]]+)(?:#{sep}\s*|$)/).collect {|m| m[0]}
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)