fiddle 1.0.6 → 1.1.0

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