fiddle 1.0.1 → 1.0.6

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: 6273f6abe03da289f77f31e82b7d43fcb99e7144f096319306e91e6d0bc33659
4
- data.tar.gz: de279d21f060c1726c701adc9dba5518bb85b179d3ac4dfd716b995948147163
3
+ metadata.gz: c38a3ad33297e304e12b74e0211d00a162ee82c7178e215ae93a9e2acf680365
4
+ data.tar.gz: 90de39682e0b7e088ae9a7570da2635e06c90b0eef90f3f060730bc7aed9b31c
5
5
  SHA512:
6
- metadata.gz: 7afc807eaa5b363d2687027ec7c4d2fffc7779286359095e96a266feb7cdbb0bf6addd8b58b5cb41cff9f1ef86764381828e172b63017cc7567d237f46c9c502
7
- data.tar.gz: 8d4cb60138cabdff92524750189ae8024faef07e16d21b9b2b10b7a7bfc7e04913bd61dd1f8482feacbb50b5b9a6f2a4e0f2515f62a6a9c32e6bb3f9ff631bc6
6
+ metadata.gz: 4b14afde84eb5dc8330ff3a394ab1049b848dc57ba8ad41563348b89338825869a9ec2c8ca5b4a657d094f2bda580e7e351fcb15e58578945726cad6a21717a3
7
+ data.tar.gz: 4540fa620b2cce64fb1dd887512df98de2b277ad76476fd54396a8fe7583bcb2b5213b3cfed4868a61769b3813033f3ed72efbe3edd9c7b65ec6fc81e1f896f7
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]
@@ -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);
@@ -220,7 +264,7 @@ value_to_generic(int type, VALUE src, fiddle_generic *dst)
220
264
  {
221
265
  /* src isn't safe from GC when type is TYPE_CONST_STRING and src
222
266
  * isn't String. */
223
- return rb_fiddle_value_to_generic(type, &src, dst);
267
+ rb_fiddle_value_to_generic(type, &src, dst);
224
268
  }
225
269
 
226
270
  VALUE
@@ -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
@@ -137,8 +137,10 @@ else
137
137
  have_func('ffi_closure_alloc', ffi_header)
138
138
  end
139
139
 
140
- if libffi
141
- $defs << "-DHAVE_FFI_PREP_CIF_VAR"
140
+ if libffi_version
141
+ if (libffi_version <=> [3, 0, 11]) >= 0
142
+ $defs << "-DHAVE_FFI_PREP_CIF_VAR"
143
+ end
142
144
  else
143
145
  have_func('ffi_prep_cif_var', ffi_header)
144
146
  end
@@ -172,14 +174,19 @@ types.each do |type, signed|
172
174
  if signed
173
175
  check_signedness(type.downcase, "stddef.h")
174
176
  end
177
+ else
178
+ check_signedness(type.downcase, "stddef.h")
175
179
  end
176
180
  end
177
181
 
182
+ if have_header("ruby/memory_view.h")
183
+ have_type("rb_memory_view_t", ["ruby/memory_view.h"])
184
+ end
185
+
178
186
  if libffi
179
187
  $LOCAL_LIBS.prepend("./#{libffi.a} ").strip! # to exts.mk
180
188
  $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)')
181
189
  end
182
- $INCFLAGS << " -I$(top_srcdir)"
183
190
  create_makefile 'fiddle' do |conf|
184
191
  if !libffi
185
192
  next conf << "LIBFFI_CLEAN = none\n"
@@ -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: */
@@ -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,7 +368,12 @@ 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
378
  rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
361
379
  #if defined(_WIN32)
@@ -433,6 +451,10 @@ Init_fiddle_function(void)
433
451
  * Caller must ensure the underlying function is called in a
434
452
  * thread-safe manner if running in a multi-threaded process.
435
453
  *
454
+ * Note that it is not thread-safe to use this method to
455
+ * directly or indirectly call many Ruby C-extension APIs unless
456
+ * you don't pass +need_gvl: true+ to Fiddle::Function#new.
457
+ *
436
458
  * For an example see Fiddle::Function
437
459
  *
438
460
  */
@@ -440,13 +462,20 @@ Init_fiddle_function(void)
440
462
 
441
463
  /*
442
464
  * Document-method: new
443
- * call-seq: new(ptr, args, ret_type, abi = DEFAULT)
465
+ * call-seq: new(ptr,
466
+ * args,
467
+ * ret_type,
468
+ * abi = DEFAULT,
469
+ * name: nil,
470
+ * need_gvl: false)
444
471
  *
445
472
  * Constructs a Function object.
446
473
  * * +ptr+ is a referenced function, of a Fiddle::Handle
447
474
  * * +args+ is an Array of arguments, passed to the +ptr+ function
448
475
  * * +ret_type+ is the return type of the function
449
476
  * * +abi+ is the ABI of the function
477
+ * * +name+ is the name of the function
478
+ * * +need_gvl+ is whether GVL is needed to call the function
450
479
  *
451
480
  */
452
481
  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 */
@@ -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
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.summary = %q{A libffi wrapper for Ruby.}
15
15
  spec.description = %q{A libffi wrapper for Ruby.}
16
16
  spec.homepage = "https://github.com/ruby/fiddle"
17
- spec.license = "BSD-2-Clause"
17
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
18
18
 
19
19
  spec.files = [
20
20
  "LICENSE.txt",
@@ -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",
@@ -153,47 +153,85 @@ module Fiddle
153
153
  return [parse_ctype(ty[0], tymap), ty[1]]
154
154
  when 'void'
155
155
  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
156
+ when /\A(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?\z/
157
+ unless Fiddle.const_defined?(:TYPE_LONG_LONG)
160
158
  raise(RuntimeError, "unsupported type: #{ty}")
161
159
  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
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)
166
163
  raise(RuntimeError, "unsupported type: #{ty}")
167
164
  end
168
- 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/
169
167
  return TYPE_LONG
170
- when /^unsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?$/
168
+ when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/
171
169
  return -TYPE_LONG
172
- when /^(?:signed\s+)?int(?:\s+\w+)?$/
170
+ when /\A(?:signed\s+)?int(?:\s+\w+)?\z/
173
171
  return TYPE_INT
174
- when /^(?:unsigned\s+int|uint)(?:\s+\w+)?$/
172
+ when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/
175
173
  return -TYPE_INT
176
- when /^(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?$/
174
+ when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/
177
175
  return TYPE_SHORT
178
- when /^unsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?$/
176
+ when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/
179
177
  return -TYPE_SHORT
180
- when /^(?:signed\s+)?char(?:\s+\w+)?$/
178
+ when /\A(?:signed\s+)?char(?:\s+\w+)?\z/
181
179
  return TYPE_CHAR
182
- when /^unsigned\s+char(?:\s+\w+)?$/
180
+ when /\Aunsigned\s+char(?:\s+\w+)?\z/
183
181
  return -TYPE_CHAR
184
- 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/
185
223
  return TYPE_FLOAT
186
- when /^double(?:\s+\w+)?$/
224
+ when /\Adouble(?:\s+\w+)?\z/
187
225
  return TYPE_DOUBLE
188
- when /^size_t(?:\s+\w+)?$/
226
+ when /\Asize_t(?:\s+\w+)?\z/
189
227
  return TYPE_SIZE_T
190
- when /^ssize_t(?:\s+\w+)?$/
228
+ when /\Assize_t(?:\s+\w+)?\z/
191
229
  return TYPE_SSIZE_T
192
- when /^ptrdiff_t(?:\s+\w+)?$/
230
+ when /\Aptrdiff_t(?:\s+\w+)?\z/
193
231
  return TYPE_PTRDIFF_T
194
- when /^intptr_t(?:\s+\w+)?$/
232
+ when /\Aintptr_t(?:\s+\w+)?\z/
195
233
  return TYPE_INTPTR_T
196
- when /^uintptr_t(?:\s+\w+)?$/
234
+ when /\Auintptr_t(?:\s+\w+)?\z/
197
235
  return TYPE_UINTPTR_T
198
236
  when /\*/, /\[[\s\d]*\]/
199
237
  return TYPE_VOIDP
@@ -213,7 +251,7 @@ module Fiddle
213
251
 
214
252
  def split_arguments(arguments, sep=',')
215
253
  return [] if arguments.strip == 'void'
216
- 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]}
217
255
  end
218
256
 
219
257
  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
@@ -1,3 +1,3 @@
1
1
  module Fiddle
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.6"
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.1
4
+ version: 1.0.6
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-17 00:00:00.000000000 Z
12
+ date: 2020-12-23 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
@@ -98,6 +99,7 @@ files:
98
99
  - lib/fiddle/version.rb
99
100
  homepage: https://github.com/ruby/fiddle
100
101
  licenses:
102
+ - Ruby
101
103
  - BSD-2-Clause
102
104
  metadata:
103
105
  msys2_mingw_dependencies: libffi
@@ -116,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
118
  - !ruby/object:Gem::Version
117
119
  version: '0'
118
120
  requirements: []
119
- rubygems_version: 3.2.0.rc.2
121
+ rubygems_version: 3.2.2
120
122
  signing_key:
121
123
  specification_version: 4
122
124
  summary: A libffi wrapper for Ruby.