fiddle 1.0.6 → 1.1.0

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: c38a3ad33297e304e12b74e0211d00a162ee82c7178e215ae93a9e2acf680365
4
- data.tar.gz: 90de39682e0b7e088ae9a7570da2635e06c90b0eef90f3f060730bc7aed9b31c
3
+ metadata.gz: 53ccf1d87df1a91951377a4baf37bf13519b15a05dd4ae6f18789027ffa69a44
4
+ data.tar.gz: 59c667cd8a70043e46e517b77700565e481d0ea69c8f7e85a5a27f98914ed357
5
5
  SHA512:
6
- metadata.gz: 4b14afde84eb5dc8330ff3a394ab1049b848dc57ba8ad41563348b89338825869a9ec2c8ca5b4a657d094f2bda580e7e351fcb15e58578945726cad6a21717a3
7
- data.tar.gz: 4540fa620b2cce64fb1dd887512df98de2b277ad76476fd54396a8fe7583bcb2b5213b3cfed4868a61769b3813033f3ed72efbe3edd9c7b65ec6fc81e1f896f7
6
+ metadata.gz: a10f7c91bde1fe0b9d9c1cc57a0b0ea1c0001e59301496cb676893f0fc948bbae570a8c78ac523a84c43b977db17ff9c2c101e7154ece15ac2b66eb4cf561618
7
+ data.tar.gz: 41be31921c03c6a153f24bfda7753c706ad0d68602fc6b59f8fe2ebe4d54282e3c0e029ff327ac2aa17bca9e66ccb593d133b6534bd677169b1a99d16ad8bfc8
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Fiddle
2
2
 
3
- [![Build Status](https://travis-ci.org/ruby/fiddle.svg?branch=master)](https://travis-ci.org/ruby/fiddle)
3
+ [![CI](https://github.com/ruby/fiddle/actions/workflows/ci.yml/badge.svg)](https://github.com/ruby/fiddle/actions/workflows/ci.yml)
4
4
 
5
5
  A libffi wrapper for Ruby.
6
6
 
data/Rakefile CHANGED
@@ -5,6 +5,18 @@ task :test do
5
5
  ruby("test/run.rb")
6
6
  end
7
7
 
8
+ namespace :version do
9
+ desc "Bump version"
10
+ task :bump do
11
+ version_rb_path = "lib/fiddle/version.rb"
12
+ version_rb = File.read(version_rb_path).gsub(/VERSION = "(.+?)"/) do
13
+ version = $1
14
+ "VERSION = \"#{version.succ}\""
15
+ end
16
+ File.write(version_rb_path, version_rb)
17
+ end
18
+ end
19
+
8
20
  require 'rake/extensiontask'
9
21
  Rake::ExtensionTask.new("fiddle")
10
22
  Rake::ExtensionTask.new("-test-/memory_view")
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);
@@ -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);
@@ -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')
@@ -146,6 +187,7 @@ else
146
187
  end
147
188
 
148
189
  have_header 'sys/mman.h'
190
+ have_header 'link.h'
149
191
 
150
192
  if have_header "dlfcn.h"
151
193
  have_library "dl"
@@ -155,10 +197,14 @@ if have_header "dlfcn.h"
155
197
  end
156
198
 
157
199
  have_func "dlerror"
200
+ have_func "dlinfo"
201
+ have_const("RTLD_DI_LINKMAP", "dlfcn.h")
158
202
  elsif have_header "windows.h"
159
- %w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
203
+ %w{ LoadLibrary FreeLibrary GetProcAddress GetModuleFileName }.each do |func|
160
204
  abort "missing function #{func}" unless have_func(func)
161
205
  end
206
+
207
+ have_library "ws2_32"
162
208
  end
163
209
 
164
210
  have_const('FFI_STDCALL', ffi_header)
@@ -179,10 +225,6 @@ types.each do |type, signed|
179
225
  end
180
226
  end
181
227
 
182
- if have_header("ruby/memory_view.h")
183
- have_type("rb_memory_view_t", ["ruby/memory_view.h"])
184
- end
185
-
186
228
  if libffi
187
229
  $LOCAL_LIBS.prepend("./#{libffi.a} ").strip! # to exts.mk
188
230
  $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)')
data/ext/fiddle/fiddle.c CHANGED
@@ -7,7 +7,7 @@ VALUE rb_eFiddleError;
7
7
  void Init_fiddle_pointer(void);
8
8
  void Init_fiddle_pinned(void);
9
9
 
10
- #ifdef FIDDLE_MEMORY_VIEW
10
+ #ifdef HAVE_RUBY_MEMORY_VIEW_H
11
11
  void Init_fiddle_memory_view(void);
12
12
  #endif
13
13
 
@@ -546,7 +546,7 @@ Init_fiddle(void)
546
546
  Init_fiddle_pointer();
547
547
  Init_fiddle_pinned();
548
548
 
549
- #ifdef FIDDLE_MEMORY_VIEW
549
+ #ifdef HAVE_RUBY_MEMORY_VIEW_H
550
550
  Init_fiddle_memory_view();
551
551
  #endif
552
552
  }
data/ext/fiddle/fiddle.h CHANGED
@@ -12,6 +12,10 @@
12
12
  #include <sys/mman.h>
13
13
  #endif
14
14
 
15
+ #if defined(HAVE_LINK_H)
16
+ # include <link.h>
17
+ #endif
18
+
15
19
  #if defined(HAVE_DLFCN_H)
16
20
  # include <dlfcn.h>
17
21
  # /* some stranger systems may not define all of these */
@@ -189,14 +193,13 @@
189
193
  #define ALIGN_INT32_T ALIGN_OF(int32_t)
190
194
  #define ALIGN_INT64_T ALIGN_OF(int64_t)
191
195
 
192
- #ifdef HAVE_TYPE_RB_MEMORY_VIEW_T
193
- # define FIDDLE_MEMORY_VIEW
194
- #endif
195
-
196
196
  extern VALUE mFiddle;
197
197
  extern VALUE rb_eFiddleDLError;
198
198
 
199
199
  VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type);
200
200
 
201
+ typedef void (*rb_fiddle_freefunc_t)(void*);
202
+ VALUE rb_fiddle_ptr_new_wrap(void *ptr, long size, rb_fiddle_freefunc_t func, VALUE wrap0, VALUE wrap1);
203
+
201
204
  #endif
202
205
  /* vim: set noet sws=4 sw=4: */
@@ -375,10 +375,18 @@ function_call(int argc, VALUE argv[], VALUE self)
375
375
  (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);
376
376
  }
377
377
 
378
- rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
378
+ {
379
+ int errno_keep = errno;
379
380
  #if defined(_WIN32)
380
- rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
381
+ DWORD error = WSAGetLastError();
382
+ int socket_error = WSAGetLastError();
383
+ rb_funcall(mFiddle, rb_intern("win32_last_error="), 1,
384
+ ULONG2NUM(error));
385
+ rb_funcall(mFiddle, rb_intern("win32_last_socket_error="), 1,
386
+ INT2NUM(socket_error));
381
387
  #endif
388
+ rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno_keep));
389
+ }
382
390
 
383
391
  ALLOCV_END(alloc_buffer);
384
392
 
data/ext/fiddle/handle.c CHANGED
@@ -259,7 +259,21 @@ rb_fiddle_handle_to_i(VALUE self)
259
259
  struct dl_handle *fiddle_handle;
260
260
 
261
261
  TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
262
- return PTR2NUM(fiddle_handle);
262
+ return PTR2NUM(fiddle_handle->ptr);
263
+ }
264
+
265
+ /*
266
+ * call-seq: to_ptr
267
+ *
268
+ * Returns the Fiddle::Pointer of this handle.
269
+ */
270
+ static VALUE
271
+ rb_fiddle_handle_to_ptr(VALUE self)
272
+ {
273
+ struct dl_handle *fiddle_handle;
274
+
275
+ TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
276
+ return rb_fiddle_ptr_new_wrap(fiddle_handle->ptr, 0, 0, self, 0);
263
277
  }
264
278
 
265
279
  static VALUE fiddle_handle_sym(void *handle, VALUE symbol);
@@ -372,6 +386,48 @@ fiddle_handle_sym(void *handle, VALUE symbol)
372
386
  return PTR2NUM(func);
373
387
  }
374
388
 
389
+ /*
390
+ * call-seq: file_name
391
+ *
392
+ * Returns the file name of this handle.
393
+ */
394
+ static VALUE
395
+ rb_fiddle_handle_file_name(VALUE self)
396
+ {
397
+ struct dl_handle *fiddle_handle;
398
+
399
+ TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
400
+
401
+ #if defined(HAVE_DLINFO) && defined(HAVE_CONST_RTLD_DI_LINKMAP)
402
+ {
403
+ struct link_map *lm = NULL;
404
+ int res = dlinfo(fiddle_handle->ptr, RTLD_DI_LINKMAP, &lm);
405
+ if (res == 0 && lm != NULL) {
406
+ return rb_str_new_cstr(lm->l_name);
407
+ }
408
+ else {
409
+ #if defined(HAVE_DLERROR)
410
+ rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
411
+ #else
412
+ rb_raise(rb_eFiddleDLError, "could not get handle file name");
413
+ #endif
414
+ }
415
+ }
416
+ #elif defined(HAVE_GETMODULEFILENAME)
417
+ {
418
+ char filename[MAX_PATH];
419
+ DWORD res = GetModuleFileName(fiddle_handle->ptr, filename, MAX_PATH);
420
+ if (res == 0) {
421
+ rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
422
+ }
423
+ return rb_str_new_cstr(filename);
424
+ }
425
+ #else
426
+ (void)fiddle_handle;
427
+ return Qnil;
428
+ #endif
429
+ }
430
+
375
431
  void
376
432
  Init_fiddle_handle(void)
377
433
  {
@@ -466,9 +522,11 @@ Init_fiddle_handle(void)
466
522
 
467
523
  rb_define_method(rb_cHandle, "initialize", rb_fiddle_handle_initialize, -1);
468
524
  rb_define_method(rb_cHandle, "to_i", rb_fiddle_handle_to_i, 0);
525
+ rb_define_method(rb_cHandle, "to_ptr", rb_fiddle_handle_to_ptr, 0);
469
526
  rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 0);
470
527
  rb_define_method(rb_cHandle, "sym", rb_fiddle_handle_sym, 1);
471
528
  rb_define_method(rb_cHandle, "[]", rb_fiddle_handle_sym, 1);
529
+ rb_define_method(rb_cHandle, "file_name", rb_fiddle_handle_file_name, 0);
472
530
  rb_define_method(rb_cHandle, "disable_close", rb_fiddle_handle_disable_close, 0);
473
531
  rb_define_method(rb_cHandle, "enable_close", rb_fiddle_handle_enable_close, 0);
474
532
  rb_define_method(rb_cHandle, "close_enabled?", rb_fiddle_handle_close_enabled_p, 0);
@@ -1,9 +1,11 @@
1
- #include <stdbool.h>
2
- #include <ruby/ruby.h>
1
+ #include <fiddle.h>
3
2
 
4
3
  #ifdef HAVE_RUBY_MEMORY_VIEW_H
5
- # include <ruby/memory_view.h>
6
- #endif
4
+
5
+ #include <stdbool.h>
6
+ #include <ruby/ruby.h>
7
+ #include <ruby/encoding.h>
8
+ #include <ruby/memory_view.h>
7
9
 
8
10
  #if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
9
11
  # define INTPTR2NUM LL2NUM
@@ -16,9 +18,6 @@
16
18
  # define UINTPTR2NUM UINT2NUM
17
19
  #endif
18
20
 
19
- #include <fiddle.h>
20
-
21
- #ifdef FIDDLE_MEMORY_VIEW
22
21
  VALUE rb_cMemoryView = Qnil;
23
22
 
24
23
  struct memview_data {
@@ -35,12 +34,25 @@ fiddle_memview_mark(void *ptr)
35
34
  }
36
35
 
37
36
  static void
38
- fiddle_memview_free(void *ptr)
37
+ fiddle_memview_release(struct memview_data *data)
39
38
  {
40
- struct memview_data *data = ptr;
39
+ if (NIL_P(data->view.obj)) return;
40
+
41
41
  rb_memory_view_release(&data->view);
42
- if (data->members)
42
+ data->view.obj = Qnil;
43
+ data->view.byte_size = 0;
44
+ if (data->members) {
43
45
  xfree(data->members);
46
+ data->members = NULL;
47
+ data->n_members = 0;
48
+ }
49
+ }
50
+
51
+ static void
52
+ fiddle_memview_free(void *ptr)
53
+ {
54
+ struct memview_data *data = ptr;
55
+ fiddle_memview_release(data);
44
56
  xfree(ptr);
45
57
  }
46
58
 
@@ -62,11 +74,32 @@ rb_fiddle_memview_s_allocate(VALUE klass)
62
74
  struct memview_data *data;
63
75
  VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data);
64
76
  data->view.obj = Qnil;
77
+ data->view.byte_size = 0;
65
78
  data->members = NULL;
66
79
  data->n_members = 0;
67
80
  return obj;
68
81
  }
69
82
 
83
+ static VALUE
84
+ rb_fiddle_memview_release(VALUE obj)
85
+ {
86
+ struct memview_data *data;
87
+ TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
88
+
89
+ if (NIL_P(data->view.obj)) return Qnil;
90
+ fiddle_memview_release(data);
91
+ return Qnil;
92
+ }
93
+
94
+ static VALUE
95
+ rb_fiddle_memview_s_export(VALUE klass, VALUE target)
96
+ {
97
+ ID id_new;
98
+ CONST_ID(id_new, "new");
99
+ VALUE memview = rb_funcall(klass, id_new, 1, target);
100
+ return rb_ensure(rb_yield, memview, rb_fiddle_memview_release, memview);
101
+ }
102
+
70
103
  static VALUE
71
104
  rb_fiddle_memview_initialize(VALUE obj, VALUE target)
72
105
  {
@@ -74,6 +107,7 @@ rb_fiddle_memview_initialize(VALUE obj, VALUE target)
74
107
  TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
75
108
 
76
109
  if (!rb_memory_view_get(target, &data->view, 0)) {
110
+ data->view.obj = Qnil;
77
111
  rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target);
78
112
  }
79
113
 
@@ -233,12 +267,44 @@ rb_fiddle_memview_aref(int argc, VALUE *argv, VALUE obj)
233
267
  return rb_memory_view_extract_item_members(ptr, data->members, data->n_members);
234
268
  }
235
269
 
270
+ static VALUE
271
+ rb_fiddle_memview_to_s(VALUE self)
272
+ {
273
+ struct memview_data *data;
274
+ const char *raw_data;
275
+ long byte_size;
276
+ VALUE string;
277
+
278
+ TypedData_Get_Struct(self,
279
+ struct memview_data,
280
+ &fiddle_memview_data_type,
281
+ data);
282
+
283
+ if (NIL_P(data->view.obj)) {
284
+ raw_data = NULL;
285
+ byte_size = 0;
286
+ } else {
287
+ raw_data = data->view.data;
288
+ byte_size = data->view.byte_size;
289
+ }
290
+
291
+ string = rb_enc_str_new_static(raw_data, byte_size, rb_ascii8bit_encoding());
292
+ {
293
+ ID id_memory_view;
294
+ CONST_ID(id_memory_view, "memory_view");
295
+ rb_ivar_set(string, id_memory_view, self);
296
+ }
297
+ return rb_obj_freeze(string);
298
+ }
299
+
236
300
  void
237
301
  Init_fiddle_memory_view(void)
238
302
  {
239
303
  rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject);
240
304
  rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate);
305
+ rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, 1);
241
306
  rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
307
+ rb_define_method(rb_cMemoryView, "release", rb_fiddle_memview_release, 0);
242
308
  rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0);
243
309
  rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0);
244
310
  rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0);
@@ -249,6 +315,7 @@ Init_fiddle_memory_view(void)
249
315
  rb_define_method(rb_cMemoryView, "strides", rb_fiddle_memview_get_strides, 0);
250
316
  rb_define_method(rb_cMemoryView, "sub_offsets", rb_fiddle_memview_get_sub_offsets, 0);
251
317
  rb_define_method(rb_cMemoryView, "[]", rb_fiddle_memview_aref, -1);
318
+ rb_define_method(rb_cMemoryView, "to_s", rb_fiddle_memview_to_s, 0);
252
319
  }
253
320
 
254
- #endif /* FIDDLE_MEMORY_VIEW */
321
+ #endif /* HAVE_RUBY_MEMORY_VIEW_H */
data/ext/fiddle/pointer.c CHANGED
@@ -6,13 +6,13 @@
6
6
  #include <ruby/ruby.h>
7
7
  #include <ruby/io.h>
8
8
 
9
+ #include <ctype.h>
10
+ #include <fiddle.h>
11
+
9
12
  #ifdef HAVE_RUBY_MEMORY_VIEW_H
10
13
  # include <ruby/memory_view.h>
11
14
  #endif
12
15
 
13
- #include <ctype.h>
14
- #include <fiddle.h>
15
-
16
16
  #ifdef PRIsVALUE
17
17
  # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
18
18
  # define RB_OBJ_STRING(obj) (obj)
@@ -24,7 +24,7 @@
24
24
 
25
25
  VALUE rb_cPointer;
26
26
 
27
- typedef void (*freefunc_t)(void*);
27
+ typedef rb_fiddle_freefunc_t freefunc_t;
28
28
 
29
29
  struct ptr_data {
30
30
  void *ptr;
@@ -92,7 +92,7 @@ static const rb_data_type_t fiddle_ptr_data_type = {
92
92
  {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,},
93
93
  };
94
94
 
95
- #ifdef FIDDLE_MEMORY_VIEW
95
+ #ifdef HAVE_RUBY_MEMORY_VIEW_H
96
96
  static struct ptr_data *
97
97
  fiddle_ptr_check_memory_view(VALUE obj)
98
98
  {
@@ -125,7 +125,7 @@ static const rb_memory_view_entry_t fiddle_ptr_memory_view_entry = {
125
125
  #endif
126
126
 
127
127
  static VALUE
128
- rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
128
+ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1)
129
129
  {
130
130
  struct ptr_data *data;
131
131
  VALUE val;
@@ -135,14 +135,22 @@ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
135
135
  data->free = func;
136
136
  data->freed = false;
137
137
  data->size = size;
138
+ data->wrap[0] = wrap0;
139
+ data->wrap[1] = wrap1;
138
140
 
139
141
  return val;
140
142
  }
141
143
 
144
+ VALUE
145
+ rb_fiddle_ptr_new_wrap(void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1)
146
+ {
147
+ return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, wrap0, wrap1);
148
+ }
149
+
142
150
  static VALUE
143
151
  rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func)
144
152
  {
145
- return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func);
153
+ return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, 0, 0);
146
154
  }
147
155
 
148
156
  static VALUE
@@ -152,7 +160,7 @@ rb_fiddle_ptr_malloc(VALUE klass, long size, freefunc_t func)
152
160
 
153
161
  ptr = ruby_xmalloc((size_t)size);
154
162
  memset(ptr,0,(size_t)size);
155
- return rb_fiddle_ptr_new2(klass, ptr, size, func);
163
+ return rb_fiddle_ptr_new2(klass, ptr, size, func, 0, 0);
156
164
  }
157
165
 
158
166
  static void *
@@ -770,6 +778,7 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
770
778
  }
771
779
  else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
772
780
  char *str = StringValuePtr(val);
781
+ wrap = val;
773
782
  ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL);
774
783
  }
775
784
  else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){
@@ -832,7 +841,7 @@ Init_fiddle_pointer(void)
832
841
  rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0);
833
842
  rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1);
834
843
 
835
- #ifdef FIDDLE_MEMORY_VIEW
844
+ #ifdef HAVE_RUBY_MEMORY_VIEW_H
836
845
  rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry);
837
846
  #endif
838
847
 
data/fiddle.gemspec CHANGED
@@ -56,11 +56,7 @@ Gem::Specification.new do |spec|
56
56
  spec.require_paths = ["lib"]
57
57
  spec.extensions = ["ext/fiddle/extconf.rb"]
58
58
 
59
- spec.required_ruby_version = ">= 2.3.0"
60
-
61
- spec.add_development_dependency "bundler"
62
- spec.add_development_dependency "rake"
63
- spec.add_development_dependency "rake-compiler"
59
+ spec.required_ruby_version = ">= 2.5.0"
64
60
 
65
61
  spec.metadata["msys2_mingw_dependencies"] = "libffi"
66
62
  end
@@ -148,9 +148,11 @@ 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
158
  when /\A(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?\z/
@@ -19,5 +19,11 @@ module Fiddle
19
19
  def to_i
20
20
  ptr.to_i
21
21
  end
22
+
23
+ # Turn this function in to a proc
24
+ def to_proc
25
+ this = self
26
+ lambda { |*args| this.call(*args) }
27
+ end
22
28
  end
23
29
  end
data/lib/fiddle/struct.rb CHANGED
@@ -13,6 +13,58 @@ module Fiddle
13
13
  CStructEntity
14
14
  end
15
15
 
16
+ def self.offsetof(name, members, types) # :nodoc:
17
+ offset = 0
18
+ worklist = name.split('.')
19
+ this_type = self
20
+ while search_name = worklist.shift
21
+ index = 0
22
+ member_index = members.index(search_name)
23
+
24
+ unless member_index
25
+ # Possibly a sub-structure
26
+ member_index = members.index { |member_name, _|
27
+ member_name == search_name
28
+ }
29
+ return unless member_index
30
+ end
31
+
32
+ types.each { |type, count = 1|
33
+ orig_offset = offset
34
+ if type.respond_to?(:entity_class)
35
+ align = type.alignment
36
+ type_size = type.size
37
+ else
38
+ align = PackInfo::ALIGN_MAP[type]
39
+ type_size = PackInfo::SIZE_MAP[type]
40
+ end
41
+
42
+ # Unions shouldn't advance the offset
43
+ if this_type.entity_class == CUnionEntity
44
+ type_size = 0
45
+ end
46
+
47
+ offset = PackInfo.align(orig_offset, align)
48
+
49
+ if worklist.empty?
50
+ return offset if index == member_index
51
+ else
52
+ if index == member_index
53
+ subtype = types[member_index]
54
+ members = subtype.members
55
+ types = subtype.types
56
+ this_type = subtype
57
+ break
58
+ end
59
+ end
60
+
61
+ offset += (type_size * count)
62
+ index += 1
63
+ }
64
+ end
65
+ nil
66
+ end
67
+
16
68
  def each
17
69
  return enum_for(__function__) unless block_given?
18
70
 
@@ -75,6 +127,10 @@ module Fiddle
75
127
  def CUnion.entity_class
76
128
  CUnionEntity
77
129
  end
130
+
131
+ def self.offsetof(name, members, types) # :nodoc:
132
+ 0
133
+ end
78
134
  end
79
135
 
80
136
  # Wrapper for arrays within a struct
@@ -172,6 +228,21 @@ module Fiddle
172
228
  define_method(:to_i){ @entity.to_i }
173
229
  define_singleton_method(:types) { types }
174
230
  define_singleton_method(:members) { members }
231
+
232
+ # Return the offset of a struct member given its name.
233
+ # For example:
234
+ #
235
+ # MyStruct = struct [
236
+ # "int64_t i",
237
+ # "char c",
238
+ # ]
239
+ #
240
+ # MyStruct.offsetof("i") # => 0
241
+ # MyStruct.offsetof("c") # => 8
242
+ #
243
+ define_singleton_method(:offsetof) { |name|
244
+ klass.offsetof(name, members, types)
245
+ }
175
246
  members.each{|name|
176
247
  name = name[0] if name.is_a?(Array) # name is a nested struct
177
248
  next if method_defined?(name)
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.6"
2
+ VERSION = "1.1.0"
3
3
  end
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
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.6
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Patterson
@@ -9,50 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-12-23 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: bundler
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - ">="
19
- - !ruby/object:Gem::Version
20
- version: '0'
21
- type: :development
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- version: '0'
28
- - !ruby/object:Gem::Dependency
29
- name: rake
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: '0'
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- version: '0'
42
- - !ruby/object:Gem::Dependency
43
- name: rake-compiler
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - ">="
47
- - !ruby/object:Gem::Version
48
- version: '0'
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- version: '0'
12
+ date: 2021-10-22 00:00:00.000000000 Z
13
+ dependencies: []
56
14
  description: A libffi wrapper for Ruby.
57
15
  email:
58
16
  - aaron@tenderlovemaking.com
@@ -111,14 +69,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
69
  requirements:
112
70
  - - ">="
113
71
  - !ruby/object:Gem::Version
114
- version: 2.3.0
72
+ version: 2.5.0
115
73
  required_rubygems_version: !ruby/object:Gem::Requirement
116
74
  requirements:
117
75
  - - ">="
118
76
  - !ruby/object:Gem::Version
119
77
  version: '0'
120
78
  requirements: []
121
- rubygems_version: 3.2.2
79
+ rubygems_version: 3.3.0.dev
122
80
  signing_key:
123
81
  specification_version: 4
124
82
  summary: A libffi wrapper for Ruby.