diff options
Diffstat (limited to 'ext/fiddle')
-rw-r--r-- | ext/fiddle/closure.c | 33 | ||||
-rw-r--r-- | ext/fiddle/conversions.c | 55 | ||||
-rw-r--r-- | ext/fiddle/conversions.h | 2 | ||||
-rw-r--r-- | ext/fiddle/depend | 24 | ||||
-rw-r--r-- | ext/fiddle/extconf.rb | 7 | ||||
-rw-r--r-- | ext/fiddle/fiddle.c | 77 | ||||
-rw-r--r-- | ext/fiddle/fiddle.gemspec | 1 | ||||
-rw-r--r-- | ext/fiddle/fiddle.h | 18 | ||||
-rw-r--r-- | ext/fiddle/function.c | 9 | ||||
-rw-r--r-- | ext/fiddle/handle.c | 9 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/cparser.rb | 28 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/import.rb | 2 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/pack.rb | 12 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/value.rb | 28 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/version.rb | 2 | ||||
-rw-r--r-- | ext/fiddle/pointer.c | 50 | ||||
-rwxr-xr-x | ext/fiddle/win32/libffi-config.rb | 10 |
17 files changed, 289 insertions, 78 deletions
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c index 892f522a62..2b4cdb6608 100644 --- a/ext/fiddle/closure.c +++ b/ext/fiddle/closure.c @@ -1,4 +1,5 @@ #include <fiddle.h> +#include <stdbool.h> #include <ruby/thread.h> int ruby_thread_has_gvl_p(void); /* from internal.h */ @@ -54,10 +55,13 @@ closure_memsize(const void * ptr) } const rb_data_type_t closure_data_type = { - "fiddle/closure", - {0, dealloc, closure_memsize,}, - 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, + .wrap_struct_name = "fiddle/closure", + .function = { + .dmark = 0, + .dfree = dealloc, + .dsize = closure_memsize + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; struct callback_args { @@ -136,6 +140,20 @@ with_gvl_callback(void *ptr) rb_ary_push(params, rb_str_new_cstr(*((const char **)(x->args[i])))); break; + case TYPE_BOOL: + if (sizeof(bool) == sizeof(char)) { + rb_ary_push(params, CBOOL2RBBOOL(*(unsigned char *)x->args[i])); + } else if (sizeof(bool) == sizeof(short)) { + rb_ary_push(params, CBOOL2RBBOOL(*(unsigned short *)x->args[i])); + } else if (sizeof(bool) == sizeof(int)) { + rb_ary_push(params, CBOOL2RBBOOL(*(unsigned int *)x->args[i])); + } else if (sizeof(bool) == sizeof(long)) { + rb_ary_push(params, CBOOL2RBBOOL(*(unsigned long *)x->args[i])); + } else { + rb_raise(rb_eNotImpError, "bool isn't supported: %u", + (unsigned int)sizeof(bool)); + } + break; default: rb_raise(rb_eRuntimeError, "closure args: %d", type); } @@ -185,6 +203,13 @@ with_gvl_callback(void *ptr) /* Dangerous. Callback must keep reference of the String. */ *((const char **)(x->resp)) = StringValueCStr(ret); break; + case TYPE_BOOL: + if (sizeof(bool) == sizeof(long)) { + *(unsigned long *)x->resp = RB_TEST(ret); + } else { + *(ffi_arg *)x->resp = RB_TEST(ret); + } + break; default: rb_raise(rb_eRuntimeError, "closure retval: %d", type); } diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c index 3b70f7de4c..796bf929c3 100644 --- a/ext/fiddle/conversions.c +++ b/ext/fiddle/conversions.c @@ -1,3 +1,5 @@ +#include <stdbool.h> + #include <fiddle.h> VALUE @@ -44,6 +46,7 @@ rb_fiddle_type_ensure(VALUE type) ID ptrdiff_t_id; ID intptr_t_id; ID uintptr_t_id; + ID bool_id; RUBY_CONST_ID(void_id, "void"); RUBY_CONST_ID(voidp_id, "voidp"); RUBY_CONST_ID(char_id, "char"); @@ -74,6 +77,7 @@ rb_fiddle_type_ensure(VALUE type) RUBY_CONST_ID(ptrdiff_t_id, "ptrdiff_t"); RUBY_CONST_ID(intptr_t_id, "intptr_t"); RUBY_CONST_ID(uintptr_t_id, "uintptr_t"); + RUBY_CONST_ID(bool_id, "bool"); if (type_id == void_id) { return INT2NUM(TYPE_VOID); } @@ -144,6 +148,9 @@ rb_fiddle_type_ensure(VALUE type) else if (type_id == uintptr_t_id) { return INT2NUM(TYPE_UINTPTR_T); } + else if (type_id == bool_id) { + return INT2NUM(TYPE_BOOL); + } else { type = original_type; } @@ -187,6 +194,20 @@ rb_fiddle_int_to_ffi_type(int type) return &ffi_type_double; case TYPE_CONST_STRING: return &ffi_type_pointer; + case TYPE_BOOL: + signed_p = 0; + if (sizeof(bool) == sizeof(char)) { + return rb_ffi_type_of(char); + } else if (sizeof(bool) == sizeof(short)) { + return rb_ffi_type_of(short); + } else if (sizeof(bool) == sizeof(int)) { + return rb_ffi_type_of(int); + } else if (sizeof(bool) == sizeof(long)) { + return rb_ffi_type_of(long); + } else { + rb_raise(rb_eNotImpError, "bool isn't supported: %u", + (unsigned int)sizeof(bool)); + } default: rb_raise(rb_eRuntimeError, "unknown type %d", type); } @@ -209,7 +230,11 @@ rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst) dst->pointer = NUM2PTR(rb_Integer(*src)); break; case TYPE_CHAR: - dst->schar = (signed char)NUM2INT(*src); + if (RB_TYPE_P(*src, RUBY_T_STRING) && RSTRING_LEN(*src) == 1) { + dst->schar = RSTRING_PTR(*src)[0]; + } else { + dst->schar = (signed char)NUM2INT(*src); + } break; case TYPE_UCHAR: dst->uchar = (unsigned char)NUM2UINT(*src); @@ -254,8 +279,23 @@ rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst) dst->pointer = rb_string_value_cstr(src); } break; + case TYPE_BOOL: + if (sizeof(bool) == sizeof(char)) { + dst->uchar = RB_TEST(*src); + } else if (sizeof(bool) == sizeof(short)) { + dst->ushort = RB_TEST(*src); + } else if (sizeof(bool) == sizeof(int)) { + dst->uint = RB_TEST(*src); + } else if (sizeof(bool) == sizeof(long)) { + dst->ulong = RB_TEST(*src); + } else { + rb_raise(rb_eNotImpError, "bool isn't supported: %u", + (unsigned int)sizeof(bool)); + } + break; default: rb_raise(rb_eRuntimeError, "unknown type %d", type); + break; } } @@ -314,6 +354,19 @@ rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval) else { return Qnil; } + case TYPE_BOOL: + if (sizeof(bool) == sizeof(char)) { + return CBOOL2RBBOOL((unsigned char)retval.fffi_arg); + } else if (sizeof(bool) == sizeof(short)) { + return CBOOL2RBBOOL((unsigned short)retval.fffi_arg); + } else if (sizeof(bool) == sizeof(int)) { + return CBOOL2RBBOOL((unsigned int)retval.fffi_arg); + } else if (sizeof(bool) == sizeof(long)) { + return CBOOL2RBBOOL(retval.ulong); + } else { + rb_raise(rb_eNotImpError, "bool isn't supported: %u", + (unsigned int)sizeof(bool)); + } default: rb_raise(rb_eRuntimeError, "unknown type %d", type); } diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h index c7c12a9234..7a1e928d56 100644 --- a/ext/fiddle/conversions.h +++ b/ext/fiddle/conversions.h @@ -50,4 +50,6 @@ VALUE generic_to_value(VALUE rettype, fiddle_generic retval); # define NUM2PTR(x) ((void*)(NUM2ULL(x))) #endif +#define CBOOL2RBBOOL(cbool) ((cbool) ? RUBY_Qtrue : RUBY_Qfalse) + #endif diff --git a/ext/fiddle/depend b/ext/fiddle/depend index d6a053f05b..561785275e 100644 --- a/ext/fiddle/depend +++ b/ext/fiddle/depend @@ -105,6 +105,7 @@ closure.o: $(hdrdir)/ruby/internal/attr/noexcept.h closure.o: $(hdrdir)/ruby/internal/attr/noinline.h closure.o: $(hdrdir)/ruby/internal/attr/nonnull.h closure.o: $(hdrdir)/ruby/internal/attr/noreturn.h +closure.o: $(hdrdir)/ruby/internal/attr/packed_struct.h closure.o: $(hdrdir)/ruby/internal/attr/pure.h closure.o: $(hdrdir)/ruby/internal/attr/restrict.h closure.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -164,7 +165,6 @@ closure.o: $(hdrdir)/ruby/internal/intern/enumerator.h closure.o: $(hdrdir)/ruby/internal/intern/error.h closure.o: $(hdrdir)/ruby/internal/intern/eval.h closure.o: $(hdrdir)/ruby/internal/intern/file.h -closure.o: $(hdrdir)/ruby/internal/intern/gc.h closure.o: $(hdrdir)/ruby/internal/intern/hash.h closure.o: $(hdrdir)/ruby/internal/intern/io.h closure.o: $(hdrdir)/ruby/internal/intern/load.h @@ -195,7 +195,6 @@ closure.o: $(hdrdir)/ruby/internal/memory.h closure.o: $(hdrdir)/ruby/internal/method.h closure.o: $(hdrdir)/ruby/internal/module.h closure.o: $(hdrdir)/ruby/internal/newobj.h -closure.o: $(hdrdir)/ruby/internal/rgengc.h closure.o: $(hdrdir)/ruby/internal/scan_args.h closure.o: $(hdrdir)/ruby/internal/special_consts.h closure.o: $(hdrdir)/ruby/internal/static_assert.h @@ -270,6 +269,7 @@ conversions.o: $(hdrdir)/ruby/internal/attr/noexcept.h conversions.o: $(hdrdir)/ruby/internal/attr/noinline.h conversions.o: $(hdrdir)/ruby/internal/attr/nonnull.h conversions.o: $(hdrdir)/ruby/internal/attr/noreturn.h +conversions.o: $(hdrdir)/ruby/internal/attr/packed_struct.h conversions.o: $(hdrdir)/ruby/internal/attr/pure.h conversions.o: $(hdrdir)/ruby/internal/attr/restrict.h conversions.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -329,7 +329,6 @@ conversions.o: $(hdrdir)/ruby/internal/intern/enumerator.h conversions.o: $(hdrdir)/ruby/internal/intern/error.h conversions.o: $(hdrdir)/ruby/internal/intern/eval.h conversions.o: $(hdrdir)/ruby/internal/intern/file.h -conversions.o: $(hdrdir)/ruby/internal/intern/gc.h conversions.o: $(hdrdir)/ruby/internal/intern/hash.h conversions.o: $(hdrdir)/ruby/internal/intern/io.h conversions.o: $(hdrdir)/ruby/internal/intern/load.h @@ -360,7 +359,6 @@ conversions.o: $(hdrdir)/ruby/internal/memory.h conversions.o: $(hdrdir)/ruby/internal/method.h conversions.o: $(hdrdir)/ruby/internal/module.h conversions.o: $(hdrdir)/ruby/internal/newobj.h -conversions.o: $(hdrdir)/ruby/internal/rgengc.h conversions.o: $(hdrdir)/ruby/internal/scan_args.h conversions.o: $(hdrdir)/ruby/internal/special_consts.h conversions.o: $(hdrdir)/ruby/internal/static_assert.h @@ -434,6 +432,7 @@ fiddle.o: $(hdrdir)/ruby/internal/attr/noexcept.h fiddle.o: $(hdrdir)/ruby/internal/attr/noinline.h fiddle.o: $(hdrdir)/ruby/internal/attr/nonnull.h fiddle.o: $(hdrdir)/ruby/internal/attr/noreturn.h +fiddle.o: $(hdrdir)/ruby/internal/attr/packed_struct.h fiddle.o: $(hdrdir)/ruby/internal/attr/pure.h fiddle.o: $(hdrdir)/ruby/internal/attr/restrict.h fiddle.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -493,7 +492,6 @@ fiddle.o: $(hdrdir)/ruby/internal/intern/enumerator.h fiddle.o: $(hdrdir)/ruby/internal/intern/error.h fiddle.o: $(hdrdir)/ruby/internal/intern/eval.h fiddle.o: $(hdrdir)/ruby/internal/intern/file.h -fiddle.o: $(hdrdir)/ruby/internal/intern/gc.h fiddle.o: $(hdrdir)/ruby/internal/intern/hash.h fiddle.o: $(hdrdir)/ruby/internal/intern/io.h fiddle.o: $(hdrdir)/ruby/internal/intern/load.h @@ -524,7 +522,6 @@ fiddle.o: $(hdrdir)/ruby/internal/memory.h fiddle.o: $(hdrdir)/ruby/internal/method.h fiddle.o: $(hdrdir)/ruby/internal/module.h fiddle.o: $(hdrdir)/ruby/internal/newobj.h -fiddle.o: $(hdrdir)/ruby/internal/rgengc.h fiddle.o: $(hdrdir)/ruby/internal/scan_args.h fiddle.o: $(hdrdir)/ruby/internal/special_consts.h fiddle.o: $(hdrdir)/ruby/internal/static_assert.h @@ -598,6 +595,7 @@ function.o: $(hdrdir)/ruby/internal/attr/noexcept.h function.o: $(hdrdir)/ruby/internal/attr/noinline.h function.o: $(hdrdir)/ruby/internal/attr/nonnull.h function.o: $(hdrdir)/ruby/internal/attr/noreturn.h +function.o: $(hdrdir)/ruby/internal/attr/packed_struct.h function.o: $(hdrdir)/ruby/internal/attr/pure.h function.o: $(hdrdir)/ruby/internal/attr/restrict.h function.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -657,7 +655,6 @@ function.o: $(hdrdir)/ruby/internal/intern/enumerator.h function.o: $(hdrdir)/ruby/internal/intern/error.h function.o: $(hdrdir)/ruby/internal/intern/eval.h function.o: $(hdrdir)/ruby/internal/intern/file.h -function.o: $(hdrdir)/ruby/internal/intern/gc.h function.o: $(hdrdir)/ruby/internal/intern/hash.h function.o: $(hdrdir)/ruby/internal/intern/io.h function.o: $(hdrdir)/ruby/internal/intern/load.h @@ -688,7 +685,6 @@ function.o: $(hdrdir)/ruby/internal/memory.h function.o: $(hdrdir)/ruby/internal/method.h function.o: $(hdrdir)/ruby/internal/module.h function.o: $(hdrdir)/ruby/internal/newobj.h -function.o: $(hdrdir)/ruby/internal/rgengc.h function.o: $(hdrdir)/ruby/internal/scan_args.h function.o: $(hdrdir)/ruby/internal/special_consts.h function.o: $(hdrdir)/ruby/internal/static_assert.h @@ -763,6 +759,7 @@ handle.o: $(hdrdir)/ruby/internal/attr/noexcept.h handle.o: $(hdrdir)/ruby/internal/attr/noinline.h handle.o: $(hdrdir)/ruby/internal/attr/nonnull.h handle.o: $(hdrdir)/ruby/internal/attr/noreturn.h +handle.o: $(hdrdir)/ruby/internal/attr/packed_struct.h handle.o: $(hdrdir)/ruby/internal/attr/pure.h handle.o: $(hdrdir)/ruby/internal/attr/restrict.h handle.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -822,7 +819,6 @@ handle.o: $(hdrdir)/ruby/internal/intern/enumerator.h handle.o: $(hdrdir)/ruby/internal/intern/error.h handle.o: $(hdrdir)/ruby/internal/intern/eval.h handle.o: $(hdrdir)/ruby/internal/intern/file.h -handle.o: $(hdrdir)/ruby/internal/intern/gc.h handle.o: $(hdrdir)/ruby/internal/intern/hash.h handle.o: $(hdrdir)/ruby/internal/intern/io.h handle.o: $(hdrdir)/ruby/internal/intern/load.h @@ -853,7 +849,6 @@ handle.o: $(hdrdir)/ruby/internal/memory.h handle.o: $(hdrdir)/ruby/internal/method.h handle.o: $(hdrdir)/ruby/internal/module.h handle.o: $(hdrdir)/ruby/internal/newobj.h -handle.o: $(hdrdir)/ruby/internal/rgengc.h handle.o: $(hdrdir)/ruby/internal/scan_args.h handle.o: $(hdrdir)/ruby/internal/special_consts.h handle.o: $(hdrdir)/ruby/internal/static_assert.h @@ -928,6 +923,7 @@ memory_view.o: $(hdrdir)/ruby/internal/attr/noexcept.h memory_view.o: $(hdrdir)/ruby/internal/attr/noinline.h memory_view.o: $(hdrdir)/ruby/internal/attr/nonnull.h memory_view.o: $(hdrdir)/ruby/internal/attr/noreturn.h +memory_view.o: $(hdrdir)/ruby/internal/attr/packed_struct.h memory_view.o: $(hdrdir)/ruby/internal/attr/pure.h memory_view.o: $(hdrdir)/ruby/internal/attr/restrict.h memory_view.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -996,7 +992,6 @@ memory_view.o: $(hdrdir)/ruby/internal/intern/enumerator.h memory_view.o: $(hdrdir)/ruby/internal/intern/error.h memory_view.o: $(hdrdir)/ruby/internal/intern/eval.h memory_view.o: $(hdrdir)/ruby/internal/intern/file.h -memory_view.o: $(hdrdir)/ruby/internal/intern/gc.h memory_view.o: $(hdrdir)/ruby/internal/intern/hash.h memory_view.o: $(hdrdir)/ruby/internal/intern/io.h memory_view.o: $(hdrdir)/ruby/internal/intern/load.h @@ -1027,7 +1022,6 @@ memory_view.o: $(hdrdir)/ruby/internal/memory.h memory_view.o: $(hdrdir)/ruby/internal/method.h memory_view.o: $(hdrdir)/ruby/internal/module.h memory_view.o: $(hdrdir)/ruby/internal/newobj.h -memory_view.o: $(hdrdir)/ruby/internal/rgengc.h memory_view.o: $(hdrdir)/ruby/internal/scan_args.h memory_view.o: $(hdrdir)/ruby/internal/special_consts.h memory_view.o: $(hdrdir)/ruby/internal/static_assert.h @@ -1104,6 +1098,7 @@ pinned.o: $(hdrdir)/ruby/internal/attr/noexcept.h pinned.o: $(hdrdir)/ruby/internal/attr/noinline.h pinned.o: $(hdrdir)/ruby/internal/attr/nonnull.h pinned.o: $(hdrdir)/ruby/internal/attr/noreturn.h +pinned.o: $(hdrdir)/ruby/internal/attr/packed_struct.h pinned.o: $(hdrdir)/ruby/internal/attr/pure.h pinned.o: $(hdrdir)/ruby/internal/attr/restrict.h pinned.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -1163,7 +1158,6 @@ pinned.o: $(hdrdir)/ruby/internal/intern/enumerator.h pinned.o: $(hdrdir)/ruby/internal/intern/error.h pinned.o: $(hdrdir)/ruby/internal/intern/eval.h pinned.o: $(hdrdir)/ruby/internal/intern/file.h -pinned.o: $(hdrdir)/ruby/internal/intern/gc.h pinned.o: $(hdrdir)/ruby/internal/intern/hash.h pinned.o: $(hdrdir)/ruby/internal/intern/io.h pinned.o: $(hdrdir)/ruby/internal/intern/load.h @@ -1194,7 +1188,6 @@ pinned.o: $(hdrdir)/ruby/internal/memory.h pinned.o: $(hdrdir)/ruby/internal/method.h pinned.o: $(hdrdir)/ruby/internal/module.h pinned.o: $(hdrdir)/ruby/internal/newobj.h -pinned.o: $(hdrdir)/ruby/internal/rgengc.h pinned.o: $(hdrdir)/ruby/internal/scan_args.h pinned.o: $(hdrdir)/ruby/internal/special_consts.h pinned.o: $(hdrdir)/ruby/internal/static_assert.h @@ -1269,6 +1262,7 @@ pointer.o: $(hdrdir)/ruby/internal/attr/noexcept.h pointer.o: $(hdrdir)/ruby/internal/attr/noinline.h pointer.o: $(hdrdir)/ruby/internal/attr/nonnull.h pointer.o: $(hdrdir)/ruby/internal/attr/noreturn.h +pointer.o: $(hdrdir)/ruby/internal/attr/packed_struct.h pointer.o: $(hdrdir)/ruby/internal/attr/pure.h pointer.o: $(hdrdir)/ruby/internal/attr/restrict.h pointer.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h @@ -1337,7 +1331,6 @@ pointer.o: $(hdrdir)/ruby/internal/intern/enumerator.h pointer.o: $(hdrdir)/ruby/internal/intern/error.h pointer.o: $(hdrdir)/ruby/internal/intern/eval.h pointer.o: $(hdrdir)/ruby/internal/intern/file.h -pointer.o: $(hdrdir)/ruby/internal/intern/gc.h pointer.o: $(hdrdir)/ruby/internal/intern/hash.h pointer.o: $(hdrdir)/ruby/internal/intern/io.h pointer.o: $(hdrdir)/ruby/internal/intern/load.h @@ -1368,7 +1361,6 @@ pointer.o: $(hdrdir)/ruby/internal/memory.h pointer.o: $(hdrdir)/ruby/internal/method.h pointer.o: $(hdrdir)/ruby/internal/module.h pointer.o: $(hdrdir)/ruby/internal/newobj.h -pointer.o: $(hdrdir)/ruby/internal/rgengc.h pointer.o: $(hdrdir)/ruby/internal/scan_args.h pointer.o: $(hdrdir)/ruby/internal/special_consts.h pointer.o: $(hdrdir)/ruby/internal/static_assert.h diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb index d550d23f79..2d85b3eea5 100644 --- a/ext/fiddle/extconf.rb +++ b/ext/fiddle/extconf.rb @@ -63,6 +63,11 @@ unless bundle end if have_ffi_header && (have_library('ffi') || have_library('libffi')) have_libffi = true + checking_for("undefined FFI_GO_CLOSURES is used") do + if egrep_cpp(/warning: 'FFI_GO_CLOSURES' is not defined/, cpp_include(ffi_header), "2>&1") + $defs.push('-DFFI_GO_CLOSURES=0') + end + end end end @@ -151,7 +156,7 @@ if libffi_version libffi_version = libffi_version.gsub(/-rc\d+/, '') libffi_version = (libffi_version.split('.').map(&:to_i) + [0,0])[0,3] $defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % libffi_version }}) - puts "libffi_version: #{libffi_version.join('.')}" + warn "libffi_version: #{libffi_version.join('.')}" end case diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c index acc1cd0837..f420d9fa3b 100644 --- a/ext/fiddle/fiddle.c +++ b/ext/fiddle/fiddle.c @@ -1,3 +1,5 @@ +#include <stdbool.h> + #include <fiddle.h> VALUE mFiddle; @@ -58,18 +60,16 @@ rb_fiddle_free(VALUE self, VALUE addr) /* * call-seq: Fiddle.dlunwrap(addr) * - * Returns the hexadecimal representation of a memory pointer address +addr+ + * Returns the Ruby object stored at the memory address +addr+ * * Example: * - * lib = Fiddle.dlopen('/lib64/libc-2.15.so') - * => #<Fiddle::Handle:0x00000001342460> - * - * lib['strcpy'].to_s(16) - * => "7f59de6dd240" - * - * Fiddle.dlunwrap(Fiddle.dlwrap(lib['strcpy'].to_s(16))) - * => "7f59de6dd240" + * x = Object.new + * # => #<Object:0x0000000107c7d870> + * Fiddle.dlwrap(x) + * # => 4425504880 + * Fiddle.dlunwrap(_) + * # => #<Object:0x0000000107c7d870> */ VALUE rb_fiddle_ptr2value(VALUE self, VALUE addr) @@ -80,15 +80,22 @@ rb_fiddle_ptr2value(VALUE self, VALUE addr) /* * call-seq: Fiddle.dlwrap(val) * - * Returns a memory pointer of a function's hexadecimal address location +val+ + * Returns the memory address of the Ruby object stored at +val+ * * Example: * - * lib = Fiddle.dlopen('/lib64/libc-2.15.so') - * => #<Fiddle::Handle:0x00000001342460> + * x = Object.new + * # => #<Object:0x0000000107c7d870> + * Fiddle.dlwrap(x) + * # => 4425504880 + * + * In the case +val+ is not a heap allocated object, this method will return + * the tagged pointer value. * - * Fiddle.dlwrap(lib['strcpy'].to_s(16)) - * => 25522520 + * Example: + * + * Fiddle.dlwrap(123) + * # => 247 */ static VALUE rb_fiddle_value2ptr(VALUE self, VALUE val) @@ -352,6 +359,12 @@ Init_fiddle(void) */ rb_define_const(mFiddleTypes, "UINTPTR_T", INT2NUM(TYPE_UINTPTR_T)); + /* Document-const: Fiddle::Types::BOOL + * + * C type - bool + */ + rb_define_const(mFiddleTypes, "BOOL" , INT2NUM(TYPE_BOOL)); + /* Document-const: ALIGN_VOIDP * * The alignment size of a void* @@ -456,6 +469,12 @@ Init_fiddle(void) */ rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t))); + /* Document-const: ALIGN_BOOL + * + * The alignment size of a bool + */ + rb_define_const(mFiddle, "ALIGN_BOOL", INT2NUM(ALIGN_OF(bool))); + /* Document-const: WINDOWS * * Returns a boolean regarding whether the host is WIN32 @@ -630,6 +649,12 @@ Init_fiddle(void) */ rb_define_const(mFiddle, "SIZEOF_CONST_STRING", INT2NUM(sizeof(const char*))); + /* Document-const: SIZEOF_BOOL + * + * size of a bool + */ + rb_define_const(mFiddle, "SIZEOF_BOOL", INT2NUM(sizeof(bool))); + /* Document-const: RUBY_FREE * * Address of the ruby_xfree() function @@ -650,6 +675,30 @@ Init_fiddle(void) rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2); rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1); + /* Document-const: Qtrue + * + * The value of Qtrue + */ + rb_define_const(mFiddle, "Qtrue", INT2NUM(Qtrue)); + + /* Document-const: Qfalse + * + * The value of Qfalse + */ + rb_define_const(mFiddle, "Qfalse", INT2NUM(Qfalse)); + + /* Document-const: Qnil + * + * The value of Qnil + */ + rb_define_const(mFiddle, "Qnil", INT2NUM(Qnil)); + + /* Document-const: Qundef + * + * The value of Qundef + */ + rb_define_const(mFiddle, "Qundef", INT2NUM(Qundef)); + Init_fiddle_function(); Init_fiddle_closure(); Init_fiddle_handle(); diff --git a/ext/fiddle/fiddle.gemspec b/ext/fiddle/fiddle.gemspec index 878109395b..3a1072dd49 100644 --- a/ext/fiddle/fiddle.gemspec +++ b/ext/fiddle/fiddle.gemspec @@ -56,4 +56,5 @@ Gem::Specification.new do |spec| spec.required_ruby_version = ">= 2.5.0" spec.metadata["msys2_mingw_dependencies"] = "libffi" + spec.metadata["changelog_uri"] = "https://github.com/ruby/fiddle/releases" end diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h index 10eb9ceedb..348baa9ab9 100644 --- a/ext/fiddle/fiddle.h +++ b/ext/fiddle/fiddle.h @@ -118,7 +118,7 @@ #define TYPE_UINT -TYPE_INT #define TYPE_LONG 5 #define TYPE_ULONG -TYPE_LONG -#if HAVE_LONG_LONG +#ifdef HAVE_LONG_LONG #define TYPE_LONG_LONG 6 #define TYPE_ULONG_LONG -TYPE_LONG_LONG #endif @@ -126,6 +126,7 @@ #define TYPE_DOUBLE 8 #define TYPE_VARIADIC 9 #define TYPE_CONST_STRING 10 +#define TYPE_BOOL 11 #define TYPE_INT8_T TYPE_CHAR #define TYPE_UINT8_T -TYPE_INT8_T @@ -196,7 +197,20 @@ #endif #define TYPE_UINTPTR_T (-TYPE_INTPTR_T) -#define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x) +/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023 + <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>. + clang versions < 8.0.0 have the same bug. */ +#if defined(HAVE__ALIGNOF) +# /* Autoconf detected availability of a sane `_Alignof()`. */ +# define ALIGN_OF(type) RB_GNUC_EXTENSION(_Alignof(type)) +#elif (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112 \ + || (defined(__GNUC__) && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \ + && !defined(__clang__)) \ + || (defined(__clang__) && __clang_major__ < 8)) +# define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x) +#else +# define ALIGN_OF(type) _Alignof(type) +#endif #define ALIGN_VOIDP ALIGN_OF(void*) #define ALIGN_CHAR ALIGN_OF(char) diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c index 274d181d17..5469e09e37 100644 --- a/ext/fiddle/function.c +++ b/ext/fiddle/function.c @@ -53,8 +53,13 @@ function_memsize(const void *p) } const rb_data_type_t function_data_type = { - "fiddle/function", - {0, deallocate, function_memsize,}, + .wrap_struct_name = "fiddle/function", + .function = { + .dmark = 0, + .dfree = deallocate, + .dsize = function_memsize + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c index ae8cc3a581..8ba416952a 100644 --- a/ext/fiddle/handle.c +++ b/ext/fiddle/handle.c @@ -50,8 +50,13 @@ fiddle_handle_memsize(const void *ptr) } static const rb_data_type_t fiddle_handle_data_type = { - "fiddle/handle", - {0, fiddle_handle_free, fiddle_handle_memsize,}, + .wrap_struct_name = "fiddle/handle", + .function = { + .dmark = 0, + .dfree = fiddle_handle_free, + .dsize = fiddle_handle_memsize + }, + .flags = RUBY_TYPED_WB_PROTECTED, }; /* diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb index 9a70402953..264ca166dd 100644 --- a/ext/fiddle/lib/fiddle/cparser.rb +++ b/ext/fiddle/lib/fiddle/cparser.rb @@ -165,18 +165,30 @@ module Fiddle raise(RuntimeError, "unsupported type: #{ty}") end return TYPE_ULONG_LONG - when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/ - return TYPE_LONG - when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/ + when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/, + /\Aunsigned\s+int\s+long(?:\s+\w+)?\z/, + /\Along(?:\s+int)?\s+unsigned(?:\s+\w+)?\z/, + /\Aint\s+unsigned\s+long(?:\s+\w+)?\z/, + /\A(?:int\s+)?long\s+unsigned(?:\s+\w+)?\z/ return TYPE_ULONG + when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/, + /\A(?:signed\s+)?int\s+long(?:\s+\w+)?\z/, + /\Along(?:\s+int)?\s+signed(?:\s+\w+)?\z/ + return TYPE_LONG + when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/, + /\Aunsigned\s+int\s+short(?:\s+\w+)?\z/, + /\Ashort(?:\s+int)?\s+unsigned(?:\s+\w+)?\z/, + /\Aint\s+unsigned\s+short(?:\s+\w+)?\z/, + /\A(?:int\s+)?short\s+unsigned(?:\s+\w+)?\z/ + return TYPE_USHORT + when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/, + /\A(?:signed\s+)?int\s+short(?:\s+\w+)?\z/, + /\Aint\s+(?:signed\s+)?short(?:\s+\w+)?\z/ + return TYPE_SHORT when /\A(?:signed\s+)?int(?:\s+\w+)?\z/ return TYPE_INT when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/ return TYPE_UINT - when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/ - return TYPE_SHORT - when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/ - return TYPE_USHORT when /\A(?:signed\s+)?char(?:\s+\w+)?\z/ return TYPE_CHAR when /\Aunsigned\s+char(?:\s+\w+)?\z/ @@ -235,6 +247,8 @@ module Fiddle return TYPE_INTPTR_T when /\Auintptr_t(?:\s+\w+)?\z/ return TYPE_UINTPTR_T + when "bool" + return TYPE_BOOL when /\*/, /\[[\s\d]*\]/ return TYPE_VOIDP when "..." diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb index 09ffcef544..050708fb96 100644 --- a/ext/fiddle/lib/fiddle/import.rb +++ b/ext/fiddle/lib/fiddle/import.rb @@ -119,6 +119,8 @@ module Fiddle return SIZEOF_VOIDP when TYPE_CONST_STRING return SIZEOF_CONST_STRING + when TYPE_BOOL + return SIZEOF_BOOL else if defined?(TYPE_LONG_LONG) and ty == TYPE_LONG_LONG diff --git a/ext/fiddle/lib/fiddle/pack.rb b/ext/fiddle/lib/fiddle/pack.rb index 545b985d50..81088f402b 100644 --- a/ext/fiddle/lib/fiddle/pack.rb +++ b/ext/fiddle/lib/fiddle/pack.rb @@ -15,6 +15,7 @@ module Fiddle TYPE_USHORT => ALIGN_SHORT, TYPE_UINT => ALIGN_INT, TYPE_ULONG => ALIGN_LONG, + TYPE_BOOL => ALIGN_BOOL, } PACK_MAP = { @@ -30,6 +31,16 @@ module Fiddle TYPE_UINT => "I!", TYPE_ULONG => "L!", } + case SIZEOF_BOOL + when SIZEOF_CHAR + PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_UCHAR] + when SIZEOF_SHORT + PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_USHORT] + when SIZEOF_INT + PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_UINT] + when SIZEOF_LONG + PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_ULONG] + end SIZE_MAP = { TYPE_VOIDP => SIZEOF_VOIDP, @@ -43,6 +54,7 @@ module Fiddle TYPE_USHORT => SIZEOF_SHORT, TYPE_UINT => SIZEOF_INT, TYPE_ULONG => SIZEOF_LONG, + TYPE_BOOL => SIZEOF_BOOL, } if defined?(TYPE_LONG_LONG) ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[TYPE_ULONG_LONG] = ALIGN_LONG_LONG diff --git a/ext/fiddle/lib/fiddle/value.rb b/ext/fiddle/lib/fiddle/value.rb index 01fec1c206..5f0b2e951e 100644 --- a/ext/fiddle/lib/fiddle/value.rb +++ b/ext/fiddle/lib/fiddle/value.rb @@ -6,17 +6,17 @@ module Fiddle def unsigned_value(val, ty) case ty.abs when TYPE_CHAR - [val].pack("c").unpack("C")[0] + [val].pack("c").unpack1("C") when TYPE_SHORT - [val].pack("s!").unpack("S!")[0] + [val].pack("s!").unpack1("S!") when TYPE_INT - [val].pack("i!").unpack("I!")[0] + [val].pack("i!").unpack1("I!") when TYPE_LONG - [val].pack("l!").unpack("L!")[0] + [val].pack("l!").unpack1("L!") else if defined?(TYPE_LONG_LONG) and ty.abs == TYPE_LONG_LONG - [val].pack("q").unpack("Q")[0] + [val].pack("q").unpack1("Q") else val end @@ -26,17 +26,17 @@ module Fiddle def signed_value(val, ty) case ty.abs when TYPE_CHAR - [val].pack("C").unpack("c")[0] + [val].pack("C").unpack1("c") when TYPE_SHORT - [val].pack("S!").unpack("s!")[0] + [val].pack("S!").unpack1("s!") when TYPE_INT - [val].pack("I!").unpack("i!")[0] + [val].pack("I!").unpack1("i!") when TYPE_LONG - [val].pack("L!").unpack("l!")[0] + [val].pack("L!").unpack1("l!") else if defined?(TYPE_LONG_LONG) and ty.abs == TYPE_LONG_LONG - [val].pack("Q").unpack("q")[0] + [val].pack("Q").unpack1("q") else val end @@ -80,11 +80,11 @@ module Fiddle else case SIZEOF_VOIDP when SIZEOF_LONG - return [arg].pack("p").unpack("l!")[0] + return [arg].pack("p").unpack1("l!") else if defined?(SIZEOF_LONG_LONG) and SIZEOF_VOIDP == SIZEOF_LONG_LONG - return [arg].pack("p").unpack("q")[0] + return [arg].pack("p").unpack1("q") else raise(RuntimeError, "sizeof(void*)?") end @@ -102,10 +102,8 @@ module Fiddle return val.unpack('C*') end end - return arg - else - return arg end + return arg else if( arg.respond_to?(:to_ptr) ) return arg.to_ptr.to_i diff --git a/ext/fiddle/lib/fiddle/version.rb b/ext/fiddle/lib/fiddle/version.rb index 719dc62e37..6c5109dca8 100644 --- a/ext/fiddle/lib/fiddle/version.rb +++ b/ext/fiddle/lib/fiddle/version.rb @@ -1,3 +1,3 @@ module Fiddle - VERSION = "1.1.1" + VERSION = "1.1.3" end diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c index 15107e3862..1b7d7a69f6 100644 --- a/ext/fiddle/pointer.c +++ b/ext/fiddle/pointer.c @@ -88,8 +88,13 @@ fiddle_ptr_memsize(const void *ptr) } static const rb_data_type_t fiddle_ptr_data_type = { - "fiddle/pointer", - {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,}, + .wrap_struct_name = "fiddle/pointer", + .function = { + .dmark = fiddle_ptr_mark, + .dfree = fiddle_ptr_free, + .dsize = fiddle_ptr_memsize, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED }; #ifdef HAVE_RUBY_MEMORY_VIEW_H @@ -135,8 +140,8 @@ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wra data->free = func; data->freed = false; data->size = size; - data->wrap[0] = wrap0; - data->wrap[1] = wrap1; + RB_OBJ_WRITE(val, &data->wrap[0], wrap0); + RB_OBJ_WRITE(val, &data->wrap[1], wrap1); return val; } @@ -235,8 +240,8 @@ rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self) /* Free previous memory. Use of inappropriate initialize may cause SEGV. */ (*(data->free))(data->ptr); } - data->wrap[0] = wrap; - data->wrap[1] = funcwrap; + RB_OBJ_WRITE(self, &data->wrap[0], wrap); + RB_OBJ_WRITE(self, &data->wrap[1], funcwrap); data->ptr = p; data->size = s; data->free = f; @@ -314,7 +319,7 @@ rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass) } obj = rb_fiddle_ptr_malloc(klass, s,f); - if (wrap) RPTR_DATA(obj)->wrap[1] = wrap; + if (wrap) RB_OBJ_WRITE(obj, &RPTR_DATA(obj)->wrap[1], wrap); if (rb_block_given_p()) { if (!f) { @@ -795,10 +800,37 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val) if (num == val) wrap = 0; ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL); } - if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap; + if (wrap) RB_OBJ_WRITE(ptr, &RPTR_DATA(ptr)->wrap[0], wrap); return ptr; } +/* + * call-seq: + * Fiddle::Pointer.read(address, len) => string + * + * Or read the memory at address +address+ with length +len+ and return a + * string with that memory + */ + +static VALUE +rb_fiddle_ptr_read_mem(VALUE klass, VALUE address, VALUE len) +{ + return rb_str_new((char *)NUM2PTR(address), NUM2ULONG(len)); +} + +/* + * call-seq: + * Fiddle::Pointer.write(address, str) + * + * Write bytes in +str+ to the location pointed to by +address+. + */ +static VALUE +rb_fiddle_ptr_write_mem(VALUE klass, VALUE addr, VALUE str) +{ + memcpy(NUM2PTR(addr), StringValuePtr(str), RSTRING_LEN(str)); + return str; +} + void Init_fiddle_pointer(void) { @@ -815,6 +847,8 @@ Init_fiddle_pointer(void) rb_define_singleton_method(rb_cPointer, "malloc", rb_fiddle_ptr_s_malloc, -1); rb_define_singleton_method(rb_cPointer, "to_ptr", rb_fiddle_ptr_s_to_ptr, 1); rb_define_singleton_method(rb_cPointer, "[]", rb_fiddle_ptr_s_to_ptr, 1); + rb_define_singleton_method(rb_cPointer, "read", rb_fiddle_ptr_read_mem, 2); + rb_define_singleton_method(rb_cPointer, "write", rb_fiddle_ptr_write_mem, 2); rb_define_method(rb_cPointer, "initialize", rb_fiddle_ptr_initialize, -1); rb_define_method(rb_cPointer, "free=", rb_fiddle_ptr_free_set, 1); rb_define_method(rb_cPointer, "free", rb_fiddle_ptr_free_get, 0); diff --git a/ext/fiddle/win32/libffi-config.rb b/ext/fiddle/win32/libffi-config.rb index 985fc29d36..8e8069a943 100755 --- a/ext/fiddle/win32/libffi-config.rb +++ b/ext/fiddle/win32/libffi-config.rb @@ -23,7 +23,7 @@ until ARGV.empty? end end -IO.foreach("#{srcdir}/configure.ac") do |line| +File.foreach("#{srcdir}/configure.ac") do |line| if /^AC_INIT\((.*)\)/ =~ line version = $1.split(/,\s*/)[1] version.gsub!(/\A\[|\]\z/, '') @@ -38,11 +38,11 @@ conf['TARGET'] = /^x64/ =~ host ? "X86_WIN64" : "X86_WIN32" FileUtils.mkdir_p([builddir, "#{builddir}/include", "#{builddir}/src/x86"]) FileUtils.cp("#{basedir}/fficonfig.h", ".", preserve: true) -hdr = IO.binread("#{srcdir}/include/ffi.h.in") +hdr = File.binread("#{srcdir}/include/ffi.h.in") hdr.gsub!(/@(\w+)@/) {conf[$1] || $&} hdr.gsub!(/^(#if\s+)@\w+@/, '\10') -IO.binwrite("#{builddir}/include/ffi.h", hdr) +File.binwrite("#{builddir}/include/ffi.h", hdr) -mk = IO.binread("#{basedir}/libffi.mk.tmpl") +mk = File.binread("#{basedir}/libffi.mk.tmpl") mk.gsub!(/@(\w+)@/) {conf[$1] || $&} -IO.binwrite("Makefile", mk) +File.binwrite("Makefile", mk) |