fiddle 1.0.3 → 1.0.8

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 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.