fiddle 1.0.3 → 1.0.4

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: b7e244560b492c43b7458506409f4d624372766d882e306a48a08fc9ad32671b
4
+ data.tar.gz: 9a166eb1dded473780e8ea89d1240da28ff6be73e72f2026eff14f6e55f060b9
5
5
  SHA512:
6
- metadata.gz: e6f266dc69d93931746b269af9698a582f1ad59430e3a35d25073e5193d12d19a94021aac5acfdee8c8c72cda6359c2a6b528e2df7d8b695c8a23ec827e1a8c4
7
- data.tar.gz: 884144e33963f0d549c90dbee74893663512f1e4eb216082cb332bb4fd62303969cbc77a03804b3c7f5f5b8a2916a96dc284c0857174ef88a308461633af5b0a
6
+ metadata.gz: 7c4509d95af60a2f16047e431580a3e6b1828b0bcf0820302d678c1b2f8e9462df767ce5a6c7e60ef728fa0d7a3afe667cbbe982e161802dafc49ed0a398bf2a
7
+ data.tar.gz: 00623b0e514fad355b76ec9d59273c15759d5991c2832c6df10c23ad06ef98f628d5d6381cfd75449ee0c2811b3f58d66b55824993c5d3aef1a2d2be1d79a8de
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);
@@ -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
@@ -177,11 +177,14 @@ types.each do |type, signed|
177
177
  end
178
178
  end
179
179
 
180
+ if have_header("ruby/memory_view.h")
181
+ have_type("rb_memory_view_t", ["ruby/memory_view.h"])
182
+ end
183
+
180
184
  if libffi
181
185
  $LOCAL_LIBS.prepend("./#{libffi.a} ").strip! # to exts.mk
182
186
  $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)')
183
187
  end
184
- $INCFLAGS << " -I$(top_srcdir)"
185
188
  create_makefile 'fiddle' do |conf|
186
189
  if !libffi
187
190
  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.len;
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_length(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.len);
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, "length", rb_fiddle_memview_get_length, 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 int
106
+ fiddle_ptr_memory_view_available_p(VALUE obj)
107
+ {
108
+ return fiddle_ptr_check_memory_view(obj) != NULL;
109
+ }
110
+
111
+ static int
112
+ fiddle_ptr_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
113
+ {
114
+ struct ptr_data *data = fiddle_ptr_check_memory_view(obj);
115
+ rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, true);
116
+
117
+ return 1;
118
+ }
119
+
120
+ static const rb_memory_view_entry_t fiddle_ptr_memory_view_entry = {
121
+ fiddle_ptr_get_memory_view,
122
+ NULL,
123
+ fiddle_ptr_memory_view_available_p
124
+ };
125
+ #endif
126
+
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
@@ -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.3"
2
+ VERSION = "1.0.4"
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.4
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: 2020-12-10 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.1.4
121
122
  signing_key:
122
123
  specification_version: 4
123
124
  summary: A libffi wrapper for Ruby.