fiddle 1.0.3 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb11df53ed0c5fb29347565ba3c56fb21ec02fe764db7f63184c1ebe5dd9ea76
4
- data.tar.gz: 3f1571515de5917bfb3215fa45382ca59808ca94d5a0c4c966c1e924f6ed9f30
3
+ metadata.gz: f60ecd26479775fa123a883a89a39ebae034c408e99bd0bc33a4d802cc04c648
4
+ data.tar.gz: 7466888aaca2242fd13af7c6663212d4c7404c4e5336626baea9c2519a068c7f
5
5
  SHA512:
6
- metadata.gz: e6f266dc69d93931746b269af9698a582f1ad59430e3a35d25073e5193d12d19a94021aac5acfdee8c8c72cda6359c2a6b528e2df7d8b695c8a23ec827e1a8c4
7
- data.tar.gz: 884144e33963f0d549c90dbee74893663512f1e4eb216082cb332bb4fd62303969cbc77a03804b3c7f5f5b8a2916a96dc284c0857174ef88a308461633af5b0a
6
+ metadata.gz: bd4349a30d8aa6b0113261cb3f53e2dee46b56b1ea72617abfbf921f31b13161897f39277358aa8e1bf3d6329d41b4b260f198ac850916eb677e7a46a21ee299
7
+ data.tar.gz: 99dd69a25bb75de362d244ebc0d4d338710b93195ce417356e44e9d7415ec7a1c0e553da2406a3ae3c5d907d705ad40e9bb9ab46eb7c95fc2ddd0aee7ea42df5
data/Rakefile CHANGED
@@ -7,5 +7,6 @@ end
7
7
 
8
8
  require 'rake/extensiontask'
9
9
  Rake::ExtensionTask.new("fiddle")
10
+ Rake::ExtensionTask.new("-test-/memory_view")
10
11
 
11
12
  task :default => [:compile, :test]
data/ext/fiddle/closure.c CHANGED
@@ -130,6 +130,10 @@ with_gvl_callback(void *ptr)
130
130
  rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)x->args[i]));
131
131
  break;
132
132
  #endif
133
+ case TYPE_CONST_STRING:
134
+ rb_ary_push(params,
135
+ rb_str_new_cstr(*((const char **)(x->args[i]))));
136
+ break;
133
137
  default:
134
138
  rb_raise(rb_eRuntimeError, "closure args: %d", type);
135
139
  }
@@ -175,6 +179,10 @@ with_gvl_callback(void *ptr)
175
179
  *(unsigned LONG_LONG *)x->resp = NUM2ULL(ret);
176
180
  break;
177
181
  #endif
182
+ case TYPE_CONST_STRING:
183
+ /* Dangerous. Callback must keep reference of the String. */
184
+ *((const char **)(x->resp)) = StringValueCStr(ret);
185
+ break;
178
186
  default:
179
187
  rb_raise(rb_eRuntimeError, "closure retval: %d", type);
180
188
  }
@@ -221,6 +229,7 @@ initialize(int rbargc, VALUE argv[], VALUE self)
221
229
  {
222
230
  VALUE ret;
223
231
  VALUE args;
232
+ VALUE normalized_args;
224
233
  VALUE abi;
225
234
  fiddle_closure * cl;
226
235
  ffi_cif * cif;
@@ -239,21 +248,26 @@ initialize(int rbargc, VALUE argv[], VALUE self)
239
248
 
240
249
  cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
241
250
 
251
+ normalized_args = rb_ary_new_capa(argc);
242
252
  for (i = 0; i < argc; i++) {
243
- int type = NUM2INT(RARRAY_AREF(args, i));
244
- cl->argv[i] = INT2FFI_TYPE(type);
253
+ VALUE arg = rb_fiddle_type_ensure(RARRAY_AREF(args, i));
254
+ rb_ary_push(normalized_args, arg);
255
+ cl->argv[i] = rb_fiddle_int_to_ffi_type(NUM2INT(arg));
245
256
  }
246
257
  cl->argv[argc] = NULL;
247
258
 
259
+ ret = rb_fiddle_type_ensure(ret);
248
260
  rb_iv_set(self, "@ctype", ret);
249
- rb_iv_set(self, "@args", args);
261
+ rb_iv_set(self, "@args", normalized_args);
250
262
 
251
263
  cif = &cl->cif;
252
264
  pcl = cl->pcl;
253
265
 
254
- result = ffi_prep_cif(cif, NUM2INT(abi), argc,
255
- INT2FFI_TYPE(NUM2INT(ret)),
256
- cl->argv);
266
+ result = ffi_prep_cif(cif,
267
+ NUM2INT(abi),
268
+ argc,
269
+ rb_fiddle_int_to_ffi_type(NUM2INT(ret)),
270
+ cl->argv);
257
271
 
258
272
  if (FFI_OK != result)
259
273
  rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
@@ -22,6 +22,18 @@ rb_fiddle_type_ensure(VALUE type)
22
22
  ID long_id;
23
23
  #ifdef TYPE_LONG_LONG
24
24
  ID long_long_id;
25
+ #endif
26
+ #ifdef TYPE_INT8_T
27
+ ID int8_t_id;
28
+ #endif
29
+ #ifdef TYPE_INT16_T
30
+ ID int16_t_id;
31
+ #endif
32
+ #ifdef TYPE_INT32_T
33
+ ID int32_t_id;
34
+ #endif
35
+ #ifdef TYPE_INT64_T
36
+ ID int64_t_id;
25
37
  #endif
26
38
  ID float_id;
27
39
  ID double_id;
@@ -40,6 +52,18 @@ rb_fiddle_type_ensure(VALUE type)
40
52
  RUBY_CONST_ID(long_id, "long");
41
53
  #ifdef TYPE_LONG_LONG
42
54
  RUBY_CONST_ID(long_long_id, "long_long");
55
+ #endif
56
+ #ifdef TYPE_INT8_T
57
+ RUBY_CONST_ID(int8_t_id, "int8_t");
58
+ #endif
59
+ #ifdef TYPE_INT16_T
60
+ RUBY_CONST_ID(int16_t_id, "int16_t");
61
+ #endif
62
+ #ifdef TYPE_INT32_T
63
+ RUBY_CONST_ID(int32_t_id, "int32_t");
64
+ #endif
65
+ #ifdef TYPE_INT64_T
66
+ RUBY_CONST_ID(int64_t_id, "int64_t");
43
67
  #endif
44
68
  RUBY_CONST_ID(float_id, "float");
45
69
  RUBY_CONST_ID(double_id, "double");
@@ -72,6 +96,26 @@ rb_fiddle_type_ensure(VALUE type)
72
96
  else if (type_id == long_long_id) {
73
97
  return INT2NUM(TYPE_LONG_LONG);
74
98
  }
99
+ #endif
100
+ #ifdef TYPE_INT8_T
101
+ else if (type_id == int8_t_id) {
102
+ return INT2NUM(TYPE_INT8_T);
103
+ }
104
+ #endif
105
+ #ifdef TYPE_INT16_T
106
+ else if (type_id == int16_t_id) {
107
+ return INT2NUM(TYPE_INT16_T);
108
+ }
109
+ #endif
110
+ #ifdef TYPE_INT32_T
111
+ else if (type_id == int32_t_id) {
112
+ return INT2NUM(TYPE_INT32_T);
113
+ }
114
+ #endif
115
+ #ifdef TYPE_INT64_T
116
+ else if (type_id == int64_t_id) {
117
+ return INT2NUM(TYPE_INT64_T);
118
+ }
75
119
  #endif
76
120
  else if (type_id == float_id) {
77
121
  return INT2NUM(TYPE_FLOAT);
@@ -24,7 +24,6 @@ typedef union
24
24
  void * pointer; /* ffi_type_pointer */
25
25
  } fiddle_generic;
26
26
 
27
- /* Deprecated. Use rb_fiddle_*() version. */
28
27
  VALUE rb_fiddle_type_ensure(VALUE type);
29
28
  ffi_type * rb_fiddle_int_to_ffi_type(int type);
30
29
  void rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst);
data/ext/fiddle/depend CHANGED
@@ -76,6 +76,8 @@ handle.o: conversions.h
76
76
  handle.o: fiddle.h
77
77
  handle.o: function.h
78
78
  handle.o: handle.c
79
+ memory_view.o: fiddle.h
80
+ memory_view.o: memory_view.c
79
81
  pointer.o: closure.h
80
82
  pointer.o: conversions.h
81
83
  pointer.o: fiddle.h
@@ -3,6 +3,47 @@ require 'mkmf'
3
3
 
4
4
  # :stopdoc:
5
5
 
6
+ def gcc?
7
+ RbConfig::CONFIG["GCC"] == "yes"
8
+ end
9
+
10
+ def disable_optimization_build_flag(flags)
11
+ if gcc?
12
+ expanded_flags = RbConfig.expand(flags.dup)
13
+ optimization_option_pattern = /(^|\s)?-O\d(\s|$)?/
14
+ if optimization_option_pattern.match?(expanded_flags)
15
+ expanded_flags.gsub(optimization_option_pattern, '\\1-Og\\2')
16
+ else
17
+ flags + " -Og"
18
+ end
19
+ else
20
+ flags
21
+ end
22
+ end
23
+
24
+ def enable_debug_build_flag(flags)
25
+ if gcc?
26
+ expanded_flags = RbConfig.expand(flags.dup)
27
+ debug_option_pattern = /(^|\s)-g(?:gdb)?\d?(\s|$)/
28
+ if debug_option_pattern.match?(expanded_flags)
29
+ expanded_flags.gsub(debug_option_pattern, '\\1-ggdb3\\2')
30
+ else
31
+ flags + " -ggdb3"
32
+ end
33
+ else
34
+ flags
35
+ end
36
+ end
37
+
38
+ checking_for(checking_message("--enable-debug-build option")) do
39
+ enable_debug_build = enable_config("debug-build", false)
40
+ if enable_debug_build
41
+ $CFLAGS = disable_optimization_build_flag($CFLAGS)
42
+ $CFLAGS = enable_debug_build_flag($CFLAGS)
43
+ end
44
+ enable_debug_build
45
+ end
46
+
6
47
  libffi_version = nil
7
48
  have_libffi = false
8
49
  bundle = enable_config('bundled-libffi')
@@ -137,8 +178,10 @@ else
137
178
  have_func('ffi_closure_alloc', ffi_header)
138
179
  end
139
180
 
140
- if libffi
141
- $defs << "-DHAVE_FFI_PREP_CIF_VAR"
181
+ if libffi_version
182
+ if (libffi_version <=> [3, 0, 11]) >= 0
183
+ $defs << "-DHAVE_FFI_PREP_CIF_VAR"
184
+ end
142
185
  else
143
186
  have_func('ffi_prep_cif_var', ffi_header)
144
187
  end
@@ -157,6 +200,8 @@ elsif have_header "windows.h"
157
200
  %w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
158
201
  abort "missing function #{func}" unless have_func(func)
159
202
  end
203
+
204
+ have_library "ws2_32"
160
205
  end
161
206
 
162
207
  have_const('FFI_STDCALL', ffi_header)
@@ -177,11 +222,14 @@ types.each do |type, signed|
177
222
  end
178
223
  end
179
224
 
225
+ if have_header("ruby/memory_view.h")
226
+ have_type("rb_memory_view_t", ["ruby/memory_view.h"])
227
+ end
228
+
180
229
  if libffi
181
230
  $LOCAL_LIBS.prepend("./#{libffi.a} ").strip! # to exts.mk
182
231
  $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)')
183
232
  end
184
- $INCFLAGS << " -I$(top_srcdir)"
185
233
  create_makefile 'fiddle' do |conf|
186
234
  if !libffi
187
235
  next conf << "LIBFFI_CLEAN = none\n"
data/ext/fiddle/fiddle.c CHANGED
@@ -7,6 +7,10 @@ VALUE rb_eFiddleError;
7
7
  void Init_fiddle_pointer(void);
8
8
  void Init_fiddle_pinned(void);
9
9
 
10
+ #ifdef FIDDLE_MEMORY_VIEW
11
+ void Init_fiddle_memory_view(void);
12
+ #endif
13
+
10
14
  /*
11
15
  * call-seq: Fiddle.malloc(size)
12
16
  *
@@ -204,6 +208,38 @@ Init_fiddle(void)
204
208
  rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG));
205
209
  #endif
206
210
 
211
+ #ifdef TYPE_INT8_T
212
+ /* Document-const: TYPE_INT8_T
213
+ *
214
+ * C type - int8_t
215
+ */
216
+ rb_define_const(mFiddle, "TYPE_INT8_T", INT2NUM(TYPE_INT8_T));
217
+ #endif
218
+
219
+ #ifdef TYPE_INT16_T
220
+ /* Document-const: TYPE_INT16_T
221
+ *
222
+ * C type - int16_t
223
+ */
224
+ rb_define_const(mFiddle, "TYPE_INT16_T", INT2NUM(TYPE_INT16_T));
225
+ #endif
226
+
227
+ #ifdef TYPE_INT32_T
228
+ /* Document-const: TYPE_INT32_T
229
+ *
230
+ * C type - int32_t
231
+ */
232
+ rb_define_const(mFiddle, "TYPE_INT32_T", INT2NUM(TYPE_INT32_T));
233
+ #endif
234
+
235
+ #ifdef TYPE_INT64_T
236
+ /* Document-const: TYPE_INT64_T
237
+ *
238
+ * C type - int64_t
239
+ */
240
+ rb_define_const(mFiddle, "TYPE_INT64_T", INT2NUM(TYPE_INT64_T));
241
+ #endif
242
+
207
243
  /* Document-const: TYPE_FLOAT
208
244
  *
209
245
  * C type - float
@@ -298,6 +334,30 @@ Init_fiddle(void)
298
334
  rb_define_const(mFiddle, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG));
299
335
  #endif
300
336
 
337
+ /* Document-const: ALIGN_INT8_T
338
+ *
339
+ * The alignment size of a int8_t
340
+ */
341
+ rb_define_const(mFiddle, "ALIGN_INT8_T", INT2NUM(ALIGN_INT8_T));
342
+
343
+ /* Document-const: ALIGN_INT16_T
344
+ *
345
+ * The alignment size of a int16_t
346
+ */
347
+ rb_define_const(mFiddle, "ALIGN_INT16_T", INT2NUM(ALIGN_INT16_T));
348
+
349
+ /* Document-const: ALIGN_INT32_T
350
+ *
351
+ * The alignment size of a int32_t
352
+ */
353
+ rb_define_const(mFiddle, "ALIGN_INT32_T", INT2NUM(ALIGN_INT32_T));
354
+
355
+ /* Document-const: ALIGN_INT64_T
356
+ *
357
+ * The alignment size of a int64_t
358
+ */
359
+ rb_define_const(mFiddle, "ALIGN_INT64_T", INT2NUM(ALIGN_INT64_T));
360
+
301
361
  /* Document-const: ALIGN_FLOAT
302
362
  *
303
363
  * The alignment size of a float
@@ -388,6 +448,30 @@ Init_fiddle(void)
388
448
  rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG)));
389
449
  #endif
390
450
 
451
+ /* Document-const: SIZEOF_INT8_T
452
+ *
453
+ * size of a int8_t
454
+ */
455
+ rb_define_const(mFiddle, "SIZEOF_INT8_T", INT2NUM(sizeof(int8_t)));
456
+
457
+ /* Document-const: SIZEOF_INT16_T
458
+ *
459
+ * size of a int16_t
460
+ */
461
+ rb_define_const(mFiddle, "SIZEOF_INT16_T", INT2NUM(sizeof(int16_t)));
462
+
463
+ /* Document-const: SIZEOF_INT32_T
464
+ *
465
+ * size of a int32_t
466
+ */
467
+ rb_define_const(mFiddle, "SIZEOF_INT32_T", INT2NUM(sizeof(int32_t)));
468
+
469
+ /* Document-const: SIZEOF_INT64_T
470
+ *
471
+ * size of a int64_t
472
+ */
473
+ rb_define_const(mFiddle, "SIZEOF_INT64_T", INT2NUM(sizeof(int64_t)));
474
+
391
475
  /* Document-const: SIZEOF_FLOAT
392
476
  *
393
477
  * size of a float
@@ -461,5 +545,9 @@ Init_fiddle(void)
461
545
  Init_fiddle_handle();
462
546
  Init_fiddle_pointer();
463
547
  Init_fiddle_pinned();
548
+
549
+ #ifdef FIDDLE_MEMORY_VIEW
550
+ Init_fiddle_memory_view();
551
+ #endif
464
552
  }
465
553
  /* vim: set noet sws=4 sw=4: */
data/ext/fiddle/fiddle.h CHANGED
@@ -58,38 +58,38 @@
58
58
  # error "CHAR_BIT not supported"
59
59
  #endif
60
60
 
61
- # if SIZEOF_SHORT == 2
62
- # define ffi_type_ushort ffi_type_uint16
63
- # define ffi_type_sshort ffi_type_sint16
64
- # elif SIZEOF_SHORT == 4
65
- # define ffi_type_ushort ffi_type_uint32
66
- # define ffi_type_sshort ffi_type_sint32
67
- # else
68
- # error "short size not supported"
69
- # endif
61
+ #if SIZEOF_SHORT == 2
62
+ # define ffi_type_ushort ffi_type_uint16
63
+ # define ffi_type_sshort ffi_type_sint16
64
+ #elif SIZEOF_SHORT == 4
65
+ # define ffi_type_ushort ffi_type_uint32
66
+ # define ffi_type_sshort ffi_type_sint32
67
+ #else
68
+ # error "short size not supported"
69
+ #endif
70
70
 
71
- # if SIZEOF_INT == 2
72
- # define ffi_type_uint ffi_type_uint16
73
- # define ffi_type_sint ffi_type_sint16
74
- # elif SIZEOF_INT == 4
75
- # define ffi_type_uint ffi_type_uint32
76
- # define ffi_type_sint ffi_type_sint32
77
- # elif SIZEOF_INT == 8
78
- # define ffi_type_uint ffi_type_uint64
79
- # define ffi_type_sint ffi_type_sint64
80
- # else
81
- # error "int size not supported"
82
- # endif
71
+ #if SIZEOF_INT == 2
72
+ # define ffi_type_uint ffi_type_uint16
73
+ # define ffi_type_sint ffi_type_sint16
74
+ #elif SIZEOF_INT == 4
75
+ # define ffi_type_uint ffi_type_uint32
76
+ # define ffi_type_sint ffi_type_sint32
77
+ #elif SIZEOF_INT == 8
78
+ # define ffi_type_uint ffi_type_uint64
79
+ # define ffi_type_sint ffi_type_sint64
80
+ #else
81
+ # error "int size not supported"
82
+ #endif
83
83
 
84
- # if SIZEOF_LONG == 4
85
- # define ffi_type_ulong ffi_type_uint32
86
- # define ffi_type_slong ffi_type_sint32
87
- # elif SIZEOF_LONG == 8
88
- # define ffi_type_ulong ffi_type_uint64
89
- # define ffi_type_slong ffi_type_sint64
90
- # else
91
- # error "long size not supported"
92
- # endif
84
+ #if SIZEOF_LONG == 4
85
+ # define ffi_type_ulong ffi_type_uint32
86
+ # define ffi_type_slong ffi_type_sint32
87
+ #elif SIZEOF_LONG == 8
88
+ # define ffi_type_ulong ffi_type_uint64
89
+ # define ffi_type_slong ffi_type_sint64
90
+ #else
91
+ # error "long size not supported"
92
+ #endif
93
93
 
94
94
  #if HAVE_LONG_LONG
95
95
  # if SIZEOF_LONG_LONG == 8
@@ -118,6 +118,27 @@
118
118
  #define TYPE_VARIADIC 9
119
119
  #define TYPE_CONST_STRING 10
120
120
 
121
+ #define TYPE_INT8_T TYPE_CHAR
122
+ #if SIZEOF_SHORT == 2
123
+ # define TYPE_INT16_T TYPE_SHORT
124
+ #elif SIZEOF_INT == 2
125
+ # define TYPE_INT16_T TYPE_INT
126
+ #endif
127
+ #if SIZEOF_SHORT == 4
128
+ # define TYPE_INT32_T TYPE_SHORT
129
+ #elif SIZEOF_INT == 4
130
+ # define TYPE_INT32_T TYPE_INT
131
+ #elif SIZEOF_LONG == 4
132
+ # define TYPE_INT32_T TYPE_LONG
133
+ #endif
134
+ #if SIZEOF_INT == 8
135
+ # define TYPE_INT64_T TYPE_INT
136
+ #elif SIZEOF_LONG == 8
137
+ # define TYPE_INT64_T TYPE_LONG
138
+ #elif defined(TYPE_LONG_LONG)
139
+ # define TYPE_INT64_T TYPE_LONG_LONG
140
+ #endif
141
+
121
142
  #ifndef TYPE_SSIZE_T
122
143
  # if SIZEOF_SIZE_T == SIZEOF_INT
123
144
  # define TYPE_SSIZE_T TYPE_INT
@@ -153,8 +174,8 @@
153
174
  #define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x)
154
175
 
155
176
  #define ALIGN_VOIDP ALIGN_OF(void*)
156
- #define ALIGN_SHORT ALIGN_OF(short)
157
177
  #define ALIGN_CHAR ALIGN_OF(char)
178
+ #define ALIGN_SHORT ALIGN_OF(short)
158
179
  #define ALIGN_INT ALIGN_OF(int)
159
180
  #define ALIGN_LONG ALIGN_OF(long)
160
181
  #if HAVE_LONG_LONG
@@ -163,6 +184,15 @@
163
184
  #define ALIGN_FLOAT ALIGN_OF(float)
164
185
  #define ALIGN_DOUBLE ALIGN_OF(double)
165
186
 
187
+ #define ALIGN_INT8_T ALIGN_OF(int8_t)
188
+ #define ALIGN_INT16_T ALIGN_OF(int16_t)
189
+ #define ALIGN_INT32_T ALIGN_OF(int32_t)
190
+ #define ALIGN_INT64_T ALIGN_OF(int64_t)
191
+
192
+ #ifdef HAVE_TYPE_RB_MEMORY_VIEW_T
193
+ # define FIDDLE_MEMORY_VIEW
194
+ #endif
195
+
166
196
  extern VALUE mFiddle;
167
197
  extern VALUE rb_eFiddleDLError;
168
198
 
@@ -77,18 +77,6 @@ rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type)
77
77
  return rb_class_new_instance(3, argv, cFiddleFunction);
78
78
  }
79
79
 
80
- static int
81
- parse_keyword_arg_i(VALUE key, VALUE value, VALUE self)
82
- {
83
- if (key == ID2SYM(rb_intern("name"))) {
84
- rb_iv_set(self, "@name", value);
85
- } else {
86
- rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE,
87
- RB_OBJ_STRING(key));
88
- }
89
- return ST_CONTINUE;
90
- }
91
-
92
80
  static VALUE
93
81
  normalize_argument_types(const char *name,
94
82
  VALUE arg_types,
@@ -134,15 +122,40 @@ static VALUE
134
122
  initialize(int argc, VALUE argv[], VALUE self)
135
123
  {
136
124
  ffi_cif * cif;
137
- VALUE ptr, arg_types, ret_type, abi, kwds;
125
+ VALUE ptr, arg_types, ret_type, abi, kwargs;
126
+ VALUE name = Qnil;
127
+ VALUE need_gvl = Qfalse;
138
128
  int c_ret_type;
139
129
  bool is_variadic = false;
140
130
  ffi_abi c_ffi_abi;
141
131
  void *cfunc;
142
132
 
143
- rb_scan_args(argc, argv, "31:", &ptr, &arg_types, &ret_type, &abi, &kwds);
133
+ rb_scan_args(argc, argv, "31:", &ptr, &arg_types, &ret_type, &abi, &kwargs);
144
134
  rb_iv_set(self, "@closure", ptr);
145
135
 
136
+ if (!NIL_P(kwargs)) {
137
+ enum {
138
+ kw_name,
139
+ kw_need_gvl,
140
+ kw_max_,
141
+ };
142
+ static ID kw[kw_max_];
143
+ VALUE args[kw_max_];
144
+ if (!kw[0]) {
145
+ kw[kw_name] = rb_intern_const("name");
146
+ kw[kw_need_gvl] = rb_intern_const("need_gvl");
147
+ }
148
+ rb_get_kwargs(kwargs, kw, 0, kw_max_, args);
149
+ if (args[kw_name] != Qundef) {
150
+ name = args[kw_name];
151
+ }
152
+ if (args[kw_need_gvl] != Qundef) {
153
+ need_gvl = args[kw_need_gvl];
154
+ }
155
+ }
156
+ rb_iv_set(self, "@name", name);
157
+ rb_iv_set(self, "@need_gvl", need_gvl);
158
+
146
159
  ptr = rb_Integer(ptr);
147
160
  cfunc = NUM2PTR(ptr);
148
161
  PTR2NUM(cfunc);
@@ -170,8 +183,6 @@ initialize(int argc, VALUE argv[], VALUE self)
170
183
  rb_iv_set(self, "@abi", abi);
171
184
  rb_iv_set(self, "@is_variadic", is_variadic ? Qtrue : Qfalse);
172
185
 
173
- if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self);
174
-
175
186
  TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
176
187
  cif->arg_types = NULL;
177
188
 
@@ -205,6 +216,7 @@ function_call(int argc, VALUE argv[], VALUE self)
205
216
  VALUE arg_types;
206
217
  VALUE cPointer;
207
218
  VALUE is_variadic;
219
+ VALUE need_gvl;
208
220
  int n_arg_types;
209
221
  int n_fixed_args = 0;
210
222
  int n_call_args = 0;
@@ -218,6 +230,7 @@ function_call(int argc, VALUE argv[], VALUE self)
218
230
  arg_types = rb_iv_get(self, "@argument_types");
219
231
  cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
220
232
  is_variadic = rb_iv_get(self, "@is_variadic");
233
+ need_gvl = rb_iv_get(self, "@need_gvl");
221
234
 
222
235
  n_arg_types = RARRAY_LENINT(arg_types);
223
236
  n_fixed_args = n_arg_types;
@@ -355,12 +368,24 @@ function_call(int argc, VALUE argv[], VALUE self)
355
368
  args.values[i_call] = NULL;
356
369
  args.fn = (void(*)(void))NUM2PTR(cfunc);
357
370
 
358
- (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);
371
+ if (RTEST(need_gvl)) {
372
+ ffi_call(args.cif, args.fn, &(args.retval), args.values);
373
+ }
374
+ else {
375
+ (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);
376
+ }
359
377
 
360
- rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
378
+ {
379
+ int errno_keep = errno;
361
380
  #if defined(_WIN32)
362
- rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
381
+ int socket_error = WSAGetLastError();
382
+ rb_funcall(mFiddle, rb_intern("win32_last_error="), 1,
383
+ INT2NUM(errno_keep));
384
+ rb_funcall(mFiddle, rb_intern("win32_last_socket_error="), 1,
385
+ INT2NUM(socket_error));
363
386
  #endif
387
+ rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno_keep));
388
+ }
364
389
 
365
390
  ALLOCV_END(alloc_buffer);
366
391
 
@@ -433,6 +458,10 @@ Init_fiddle_function(void)
433
458
  * Caller must ensure the underlying function is called in a
434
459
  * thread-safe manner if running in a multi-threaded process.
435
460
  *
461
+ * Note that it is not thread-safe to use this method to
462
+ * directly or indirectly call many Ruby C-extension APIs unless
463
+ * you don't pass +need_gvl: true+ to Fiddle::Function#new.
464
+ *
436
465
  * For an example see Fiddle::Function
437
466
  *
438
467
  */
@@ -440,13 +469,20 @@ Init_fiddle_function(void)
440
469
 
441
470
  /*
442
471
  * Document-method: new
443
- * call-seq: new(ptr, args, ret_type, abi = DEFAULT)
472
+ * call-seq: new(ptr,
473
+ * args,
474
+ * ret_type,
475
+ * abi = DEFAULT,
476
+ * name: nil,
477
+ * need_gvl: false)
444
478
  *
445
479
  * Constructs a Function object.
446
480
  * * +ptr+ is a referenced function, of a Fiddle::Handle
447
481
  * * +args+ is an Array of arguments, passed to the +ptr+ function
448
482
  * * +ret_type+ is the return type of the function
449
483
  * * +abi+ is the ABI of the function
484
+ * * +name+ is the name of the function
485
+ * * +need_gvl+ is whether GVL is needed to call the function
450
486
  *
451
487
  */
452
488
  rb_define_method(cFiddleFunction, "initialize", initialize, -1);
@@ -0,0 +1,254 @@
1
+ #include <stdbool.h>
2
+ #include <ruby/ruby.h>
3
+
4
+ #ifdef HAVE_RUBY_MEMORY_VIEW_H
5
+ # include <ruby/memory_view.h>
6
+ #endif
7
+
8
+ #if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
9
+ # define INTPTR2NUM LL2NUM
10
+ # define UINTPTR2NUM ULL2NUM
11
+ #elif SIZEOF_INTPTR_T == SIZEOF_LONG
12
+ # define INTPTR2NUM LONG2NUM
13
+ # define UINTPTR2NUM ULONG2NUM
14
+ #else
15
+ # define INTPTR2NUM INT2NUM
16
+ # define UINTPTR2NUM UINT2NUM
17
+ #endif
18
+
19
+ #include <fiddle.h>
20
+
21
+ #ifdef FIDDLE_MEMORY_VIEW
22
+ VALUE rb_cMemoryView = Qnil;
23
+
24
+ struct memview_data {
25
+ rb_memory_view_t view;
26
+ rb_memory_view_item_component_t *members;
27
+ size_t n_members;
28
+ };
29
+
30
+ static void
31
+ fiddle_memview_mark(void *ptr)
32
+ {
33
+ const struct memview_data *data = ptr;
34
+ rb_gc_mark(data->view.obj);
35
+ }
36
+
37
+ static void
38
+ fiddle_memview_free(void *ptr)
39
+ {
40
+ struct memview_data *data = ptr;
41
+ rb_memory_view_release(&data->view);
42
+ if (data->members)
43
+ xfree(data->members);
44
+ xfree(ptr);
45
+ }
46
+
47
+ static size_t
48
+ fiddle_memview_memsize(const void *ptr)
49
+ {
50
+ const struct memview_data *data = ptr;
51
+ return sizeof(*data) + sizeof(rb_memory_view_item_component_t)*data->n_members + (size_t)data->view.byte_size;
52
+ }
53
+
54
+ static const rb_data_type_t fiddle_memview_data_type = {
55
+ "fiddle/memory_view",
56
+ {fiddle_memview_mark, fiddle_memview_free, fiddle_memview_memsize,},
57
+ };
58
+
59
+ static VALUE
60
+ rb_fiddle_memview_s_allocate(VALUE klass)
61
+ {
62
+ struct memview_data *data;
63
+ VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data);
64
+ data->view.obj = Qnil;
65
+ data->members = NULL;
66
+ data->n_members = 0;
67
+ return obj;
68
+ }
69
+
70
+ static VALUE
71
+ rb_fiddle_memview_initialize(VALUE obj, VALUE target)
72
+ {
73
+ struct memview_data *data;
74
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
75
+
76
+ if (!rb_memory_view_get(target, &data->view, 0)) {
77
+ rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target);
78
+ }
79
+
80
+ return Qnil;
81
+ }
82
+
83
+ static VALUE
84
+ rb_fiddle_memview_get_obj(VALUE obj)
85
+ {
86
+ struct memview_data *data;
87
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
88
+
89
+ return data->view.obj;
90
+ }
91
+
92
+ static VALUE
93
+ rb_fiddle_memview_get_byte_size(VALUE obj)
94
+ {
95
+ struct memview_data *data;
96
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
97
+
98
+ if (NIL_P(data->view.obj)) return Qnil;
99
+ return SSIZET2NUM(data->view.byte_size);
100
+ }
101
+
102
+ static VALUE
103
+ rb_fiddle_memview_get_readonly(VALUE obj)
104
+ {
105
+ struct memview_data *data;
106
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
107
+
108
+ if (NIL_P(data->view.obj)) return Qnil;
109
+ return data->view.readonly ? Qtrue : Qfalse;
110
+ }
111
+
112
+ static VALUE
113
+ rb_fiddle_memview_get_format(VALUE obj)
114
+ {
115
+ struct memview_data *data;
116
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
117
+
118
+ if (NIL_P(data->view.obj)) return Qnil;
119
+ return data->view.format == NULL ? Qnil : rb_str_new_cstr(data->view.format);
120
+ }
121
+
122
+ static VALUE
123
+ rb_fiddle_memview_get_item_size(VALUE obj)
124
+ {
125
+ struct memview_data *data;
126
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
127
+
128
+ if (NIL_P(data->view.obj)) return Qnil;
129
+ return SSIZET2NUM(data->view.item_size);
130
+ }
131
+
132
+ static VALUE
133
+ rb_fiddle_memview_get_ndim(VALUE obj)
134
+ {
135
+ struct memview_data *data;
136
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
137
+
138
+ if (NIL_P(data->view.obj)) return Qnil;
139
+ return SSIZET2NUM(data->view.ndim);
140
+ }
141
+
142
+ static VALUE
143
+ rb_fiddle_memview_get_shape(VALUE obj)
144
+ {
145
+ struct memview_data *data;
146
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
147
+
148
+ if (NIL_P(data->view.obj)) return Qnil;
149
+ if (data->view.shape == NULL) return Qnil;
150
+
151
+ const ssize_t ndim = data->view.ndim;
152
+ VALUE shape = rb_ary_new_capa(ndim);
153
+ ssize_t i;
154
+ for (i = 0; i < ndim; ++i) {
155
+ rb_ary_push(shape, SSIZET2NUM(data->view.shape[i]));
156
+ }
157
+ return shape;
158
+ }
159
+
160
+ static VALUE
161
+ rb_fiddle_memview_get_strides(VALUE obj)
162
+ {
163
+ struct memview_data *data;
164
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
165
+
166
+ if (NIL_P(data->view.obj)) return Qnil;
167
+ if (data->view.strides == NULL) return Qnil;
168
+
169
+ const ssize_t ndim = data->view.ndim;
170
+ VALUE strides = rb_ary_new_capa(ndim);
171
+ ssize_t i;
172
+ for (i = 0; i < ndim; ++i) {
173
+ rb_ary_push(strides, SSIZET2NUM(data->view.strides[i]));
174
+ }
175
+ return strides;
176
+ }
177
+
178
+ static VALUE
179
+ rb_fiddle_memview_get_sub_offsets(VALUE obj)
180
+ {
181
+ struct memview_data *data;
182
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
183
+
184
+ if (NIL_P(data->view.obj)) return Qnil;
185
+ if (data->view.sub_offsets == NULL) return Qnil;
186
+
187
+ const ssize_t ndim = data->view.ndim;
188
+ VALUE sub_offsets = rb_ary_new_capa(ndim);
189
+ ssize_t i;
190
+ for (i = 0; i < ndim; ++i) {
191
+ rb_ary_push(sub_offsets, SSIZET2NUM(data->view.sub_offsets[i]));
192
+ }
193
+ return sub_offsets;
194
+ }
195
+
196
+ static VALUE
197
+ rb_fiddle_memview_aref(int argc, VALUE *argv, VALUE obj)
198
+ {
199
+ struct memview_data *data;
200
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
201
+
202
+ if (NIL_P(data->view.obj)) return Qnil;
203
+
204
+ const ssize_t ndim = data->view.ndim;
205
+ if (argc != ndim) {
206
+ rb_raise(rb_eIndexError, "wrong number of index (%d for %"PRIdSIZE")", argc, ndim);
207
+ }
208
+
209
+ VALUE indices_v = 0;
210
+ ssize_t *indices = ALLOCV_N(ssize_t, indices_v, ndim);
211
+
212
+ ssize_t i;
213
+ for (i = 0; i < ndim; ++i) {
214
+ ssize_t x = NUM2SSIZET(argv[i]);
215
+ indices[i] = x;
216
+ }
217
+
218
+ uint8_t *ptr = rb_memory_view_get_item_pointer(&data->view, indices);
219
+ ALLOCV_END(indices_v);
220
+
221
+ if (data->view.format == NULL) {
222
+ return INT2FIX(*ptr);
223
+ }
224
+
225
+ if (!data->members) {
226
+ const char *err;
227
+ if (rb_memory_view_parse_item_format(data->view.format, &data->members, &data->n_members, &err) < 0) {
228
+ rb_raise(rb_eRuntimeError, "Unable to recognize item format at %"PRIdSIZE" in \"%s\"",
229
+ err - data->view.format, data->view.format);
230
+ }
231
+ }
232
+
233
+ return rb_memory_view_extract_item_members(ptr, data->members, data->n_members);
234
+ }
235
+
236
+ void
237
+ Init_fiddle_memory_view(void)
238
+ {
239
+ rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject);
240
+ rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate);
241
+ rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
242
+ rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0);
243
+ rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0);
244
+ rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0);
245
+ rb_define_method(rb_cMemoryView, "format", rb_fiddle_memview_get_format, 0);
246
+ rb_define_method(rb_cMemoryView, "item_size", rb_fiddle_memview_get_item_size, 0);
247
+ rb_define_method(rb_cMemoryView, "ndim", rb_fiddle_memview_get_ndim, 0);
248
+ rb_define_method(rb_cMemoryView, "shape", rb_fiddle_memview_get_shape, 0);
249
+ rb_define_method(rb_cMemoryView, "strides", rb_fiddle_memview_get_strides, 0);
250
+ rb_define_method(rb_cMemoryView, "sub_offsets", rb_fiddle_memview_get_sub_offsets, 0);
251
+ rb_define_method(rb_cMemoryView, "[]", rb_fiddle_memview_aref, -1);
252
+ }
253
+
254
+ #endif /* FIDDLE_MEMORY_VIEW */
data/ext/fiddle/pointer.c CHANGED
@@ -5,6 +5,11 @@
5
5
  #include <stdbool.h>
6
6
  #include <ruby/ruby.h>
7
7
  #include <ruby/io.h>
8
+
9
+ #ifdef HAVE_RUBY_MEMORY_VIEW_H
10
+ # include <ruby/memory_view.h>
11
+ #endif
12
+
8
13
  #include <ctype.h>
9
14
  #include <fiddle.h>
10
15
 
@@ -87,6 +92,38 @@ static const rb_data_type_t fiddle_ptr_data_type = {
87
92
  {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,},
88
93
  };
89
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 bool
106
+ fiddle_ptr_memory_view_available_p(VALUE obj)
107
+ {
108
+ return fiddle_ptr_check_memory_view(obj) != NULL;
109
+ }
110
+
111
+ static bool
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 true;
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
+
90
127
  static VALUE
91
128
  rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
92
129
  {
@@ -795,6 +832,10 @@ Init_fiddle_pointer(void)
795
832
  rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0);
796
833
  rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1);
797
834
 
835
+ #ifdef FIDDLE_MEMORY_VIEW
836
+ rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry);
837
+ #endif
838
+
798
839
  /* Document-const: NULL
799
840
  *
800
841
  * A NULL pointer
data/fiddle.gemspec CHANGED
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
34
34
  "ext/fiddle/function.c",
35
35
  "ext/fiddle/function.h",
36
36
  "ext/fiddle/handle.c",
37
+ "ext/fiddle/memory_view.c",
37
38
  "ext/fiddle/pinned.c",
38
39
  "ext/fiddle/pointer.c",
39
40
  "ext/fiddle/win32/fficonfig.h",
data/lib/fiddle.rb CHANGED
@@ -17,6 +17,18 @@ module Fiddle
17
17
  def self.win32_last_error= error
18
18
  Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
19
19
  end
20
+
21
+ # Returns the last win32 socket +Error+ of the current executing
22
+ # +Thread+ or nil if none
23
+ def self.win32_last_socket_error
24
+ Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
25
+ end
26
+
27
+ # Sets the last win32 socket +Error+ of the current executing
28
+ # +Thread+ to +error+
29
+ def self.win32_last_socket_error= error
30
+ Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
31
+ end
20
32
  end
21
33
 
22
34
  # Returns the last +Error+ of the current executing +Thread+ or nil if none
@@ -148,52 +148,92 @@ module Fiddle
148
148
  #
149
149
  def parse_ctype(ty, tymap=nil)
150
150
  tymap ||= {}
151
- case ty
152
- when Array
151
+ if ty.is_a?(Array)
153
152
  return [parse_ctype(ty[0], tymap), ty[1]]
153
+ end
154
+ ty = ty.gsub(/\Aconst\s+/, "")
155
+ case ty
154
156
  when 'void'
155
157
  return TYPE_VOID
156
- when /^(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?$/
157
- if( defined?(TYPE_LONG_LONG) )
158
- return TYPE_LONG_LONG
159
- else
158
+ when /\A(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?\z/
159
+ unless Fiddle.const_defined?(:TYPE_LONG_LONG)
160
160
  raise(RuntimeError, "unsupported type: #{ty}")
161
161
  end
162
- when /^(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?$/
163
- if( defined?(TYPE_LONG_LONG) )
164
- return -TYPE_LONG_LONG
165
- else
162
+ return TYPE_LONG_LONG
163
+ when /\A(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?\z/
164
+ unless Fiddle.const_defined?(:TYPE_LONG_LONG)
166
165
  raise(RuntimeError, "unsupported type: #{ty}")
167
166
  end
168
- when /^(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?$/
167
+ return -TYPE_LONG_LONG
168
+ when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/
169
169
  return TYPE_LONG
170
- when /^unsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?$/
170
+ when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/
171
171
  return -TYPE_LONG
172
- when /^(?:signed\s+)?int(?:\s+\w+)?$/
172
+ when /\A(?:signed\s+)?int(?:\s+\w+)?\z/
173
173
  return TYPE_INT
174
- when /^(?:unsigned\s+int|uint)(?:\s+\w+)?$/
174
+ when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/
175
175
  return -TYPE_INT
176
- when /^(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?$/
176
+ when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/
177
177
  return TYPE_SHORT
178
- when /^unsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?$/
178
+ when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/
179
179
  return -TYPE_SHORT
180
- when /^(?:signed\s+)?char(?:\s+\w+)?$/
180
+ when /\A(?:signed\s+)?char(?:\s+\w+)?\z/
181
181
  return TYPE_CHAR
182
- when /^unsigned\s+char(?:\s+\w+)?$/
182
+ when /\Aunsigned\s+char(?:\s+\w+)?\z/
183
183
  return -TYPE_CHAR
184
- when /^float(?:\s+\w+)?$/
184
+ when /\Aint8_t(?:\s+\w+)?\z/
185
+ unless Fiddle.const_defined?(:TYPE_INT8_T)
186
+ raise(RuntimeError, "unsupported type: #{ty}")
187
+ end
188
+ return TYPE_INT8_T
189
+ when /\Auint8_t(?:\s+\w+)?\z/
190
+ unless Fiddle.const_defined?(:TYPE_INT8_T)
191
+ raise(RuntimeError, "unsupported type: #{ty}")
192
+ end
193
+ return -TYPE_INT8_T
194
+ when /\Aint16_t(?:\s+\w+)?\z/
195
+ unless Fiddle.const_defined?(:TYPE_INT16_T)
196
+ raise(RuntimeError, "unsupported type: #{ty}")
197
+ end
198
+ return TYPE_INT16_T
199
+ when /\Auint16_t(?:\s+\w+)?\z/
200
+ unless Fiddle.const_defined?(:TYPE_INT16_T)
201
+ raise(RuntimeError, "unsupported type: #{ty}")
202
+ end
203
+ return -TYPE_INT16_T
204
+ when /\Aint32_t(?:\s+\w+)?\z/
205
+ unless Fiddle.const_defined?(:TYPE_INT32_T)
206
+ raise(RuntimeError, "unsupported type: #{ty}")
207
+ end
208
+ return TYPE_INT32_T
209
+ when /\Auint32_t(?:\s+\w+)?\z/
210
+ unless Fiddle.const_defined?(:TYPE_INT32_T)
211
+ raise(RuntimeError, "unsupported type: #{ty}")
212
+ end
213
+ return -TYPE_INT32_T
214
+ when /\Aint64_t(?:\s+\w+)?\z/
215
+ unless Fiddle.const_defined?(:TYPE_INT64_T)
216
+ raise(RuntimeError, "unsupported type: #{ty}")
217
+ end
218
+ return TYPE_INT64_T
219
+ when /\Auint64_t(?:\s+\w+)?\z/
220
+ unless Fiddle.const_defined?(:TYPE_INT64_T)
221
+ raise(RuntimeError, "unsupported type: #{ty}")
222
+ end
223
+ return -TYPE_INT64_T
224
+ when /\Afloat(?:\s+\w+)?\z/
185
225
  return TYPE_FLOAT
186
- when /^double(?:\s+\w+)?$/
226
+ when /\Adouble(?:\s+\w+)?\z/
187
227
  return TYPE_DOUBLE
188
- when /^size_t(?:\s+\w+)?$/
228
+ when /\Asize_t(?:\s+\w+)?\z/
189
229
  return TYPE_SIZE_T
190
- when /^ssize_t(?:\s+\w+)?$/
230
+ when /\Assize_t(?:\s+\w+)?\z/
191
231
  return TYPE_SSIZE_T
192
- when /^ptrdiff_t(?:\s+\w+)?$/
232
+ when /\Aptrdiff_t(?:\s+\w+)?\z/
193
233
  return TYPE_PTRDIFF_T
194
- when /^intptr_t(?:\s+\w+)?$/
234
+ when /\Aintptr_t(?:\s+\w+)?\z/
195
235
  return TYPE_INTPTR_T
196
- when /^uintptr_t(?:\s+\w+)?$/
236
+ when /\Auintptr_t(?:\s+\w+)?\z/
197
237
  return TYPE_UINTPTR_T
198
238
  when /\*/, /\[[\s\d]*\]/
199
239
  return TYPE_VOIDP
@@ -213,7 +253,7 @@ module Fiddle
213
253
 
214
254
  def split_arguments(arguments, sep=',')
215
255
  return [] if arguments.strip == 'void'
216
- arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+|\.\.\.)(?:#{sep}\s*|$)/).collect {|m| m[0]}
256
+ arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+|\.\.\.)(?:#{sep}\s*|\z)/).collect {|m| m[0]}
217
257
  end
218
258
 
219
259
  def compact(signature)
@@ -10,6 +10,11 @@ module Fiddle
10
10
  # The name of this function
11
11
  attr_reader :name
12
12
 
13
+ # Whether GVL is needed to call this function
14
+ def need_gvl?
15
+ @need_gvl
16
+ end
17
+
13
18
  # The integer memory location of this function
14
19
  def to_i
15
20
  ptr.to_i
data/lib/fiddle/types.rb CHANGED
@@ -27,28 +27,29 @@ module Fiddle
27
27
  # * WORD
28
28
  module Win32Types
29
29
  def included(m) # :nodoc:
30
+ # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
30
31
  m.module_eval{
31
- typealias "DWORD", "unsigned long"
32
- typealias "PDWORD", "unsigned long *"
33
- typealias "DWORD32", "unsigned long"
34
- typealias "DWORD64", "unsigned long long"
35
- typealias "WORD", "unsigned short"
36
- typealias "PWORD", "unsigned short *"
32
+ typealias "ATOM", "WORD"
37
33
  typealias "BOOL", "int"
38
- typealias "ATOM", "int"
39
34
  typealias "BYTE", "unsigned char"
40
- typealias "PBYTE", "unsigned char *"
35
+ typealias "DWORD", "unsigned long"
36
+ typealias "DWORD32", "uint32_t"
37
+ typealias "DWORD64", "uint64_t"
38
+ typealias "HANDLE", "PVOID"
39
+ typealias "HDC", "HANDLE"
40
+ typealias "HINSTANCE", "HANDLE"
41
+ typealias "HWND", "HANDLE"
42
+ typealias "LPCSTR", "const char *"
43
+ typealias "LPSTR", "char *"
44
+ typealias "PBYTE", "BYTE *"
45
+ typealias "PDWORD", "DWORD *"
46
+ typealias "PHANDLE", "HANDLE *"
47
+ typealias "PVOID", "void *"
48
+ typealias "PWORD", "WORD *"
49
+ typealias "UCHAR", "unsigned char"
41
50
  typealias "UINT", "unsigned int"
42
51
  typealias "ULONG", "unsigned long"
43
- typealias "UCHAR", "unsigned char"
44
- typealias "HANDLE", "uintptr_t"
45
- typealias "PHANDLE", "void*"
46
- typealias "PVOID", "void*"
47
- typealias "LPCSTR", "char*"
48
- typealias "LPSTR", "char*"
49
- typealias "HINSTANCE", "unsigned int"
50
- typealias "HDC", "unsigned int"
51
- typealias "HWND", "unsigned int"
52
+ typealias "WORD", "unsigned short"
52
53
  }
53
54
  end
54
55
  module_function :included
@@ -1,3 +1,3 @@
1
1
  module Fiddle
2
- VERSION = "1.0.3"
2
+ VERSION = "1.0.8"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fiddle
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Patterson
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-11-21 00:00:00.000000000 Z
12
+ date: 2021-04-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -79,6 +79,7 @@ files:
79
79
  - ext/fiddle/function.c
80
80
  - ext/fiddle/function.h
81
81
  - ext/fiddle/handle.c
82
+ - ext/fiddle/memory_view.c
82
83
  - ext/fiddle/pinned.c
83
84
  - ext/fiddle/pointer.c
84
85
  - ext/fiddle/win32/fficonfig.h
@@ -117,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
118
  - !ruby/object:Gem::Version
118
119
  version: '0'
119
120
  requirements: []
120
- rubygems_version: 3.2.0.rc.2
121
+ rubygems_version: 3.3.0.dev
121
122
  signing_key:
122
123
  specification_version: 4
123
124
  summary: A libffi wrapper for Ruby.