diff options
Diffstat (limited to 'ext/fiddle')
-rw-r--r-- | ext/fiddle/closure.c | 164 | ||||
-rw-r--r-- | ext/fiddle/conversions.c | 75 | ||||
-rw-r--r-- | ext/fiddle/conversions.h | 2 | ||||
-rw-r--r-- | ext/fiddle/depend | 40 | ||||
-rw-r--r-- | ext/fiddle/extconf.rb | 33 | ||||
-rw-r--r-- | ext/fiddle/extlibs | 13 | ||||
-rw-r--r-- | ext/fiddle/fiddle.c | 267 | ||||
-rw-r--r-- | ext/fiddle/fiddle.gemspec | 4 | ||||
-rw-r--r-- | ext/fiddle/fiddle.h | 39 | ||||
-rw-r--r-- | ext/fiddle/function.c | 9 | ||||
-rw-r--r-- | ext/fiddle/handle.c | 68 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle.rb | 35 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/closure.rb | 25 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/cparser.rb | 42 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/import.rb | 2 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/pack.rb | 47 | ||||
-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 |
20 files changed, 732 insertions, 223 deletions
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c index 3679e5c9ad..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,8 +55,13 @@ closure_memsize(const void * ptr) } const rb_data_type_t closure_data_type = { - "fiddle/closure", - {0, dealloc, closure_memsize,}, + .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 { @@ -90,7 +96,7 @@ with_gvl_callback(void *ptr) case TYPE_INT: rb_ary_push(params, INT2NUM(*(int *)x->args[i])); break; - case -TYPE_INT: + case TYPE_UINT: rb_ary_push(params, UINT2NUM(*(unsigned int *)x->args[i])); break; case TYPE_VOIDP: @@ -101,19 +107,19 @@ with_gvl_callback(void *ptr) case TYPE_LONG: rb_ary_push(params, LONG2NUM(*(long *)x->args[i])); break; - case -TYPE_LONG: + case TYPE_ULONG: rb_ary_push(params, ULONG2NUM(*(unsigned long *)x->args[i])); break; case TYPE_CHAR: rb_ary_push(params, INT2NUM(*(signed char *)x->args[i])); break; - case -TYPE_CHAR: + case TYPE_UCHAR: rb_ary_push(params, UINT2NUM(*(unsigned char *)x->args[i])); break; case TYPE_SHORT: rb_ary_push(params, INT2NUM(*(signed short *)x->args[i])); break; - case -TYPE_SHORT: + case TYPE_USHORT: rb_ary_push(params, UINT2NUM(*(unsigned short *)x->args[i])); break; case TYPE_DOUBLE: @@ -126,7 +132,7 @@ with_gvl_callback(void *ptr) case TYPE_LONG_LONG: rb_ary_push(params, LL2NUM(*(LONG_LONG *)x->args[i])); break; - case -TYPE_LONG_LONG: + case TYPE_ULONG_LONG: rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)x->args[i])); break; #endif @@ -134,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); } @@ -149,7 +169,7 @@ with_gvl_callback(void *ptr) case TYPE_LONG: *(long *)x->resp = NUM2LONG(ret); break; - case -TYPE_LONG: + case TYPE_ULONG: *(unsigned long *)x->resp = NUM2ULONG(ret); break; case TYPE_CHAR: @@ -157,9 +177,9 @@ with_gvl_callback(void *ptr) case TYPE_INT: *(ffi_sarg *)x->resp = NUM2INT(ret); break; - case -TYPE_CHAR: - case -TYPE_SHORT: - case -TYPE_INT: + case TYPE_UCHAR: + case TYPE_USHORT: + case TYPE_UINT: *(ffi_arg *)x->resp = NUM2UINT(ret); break; case TYPE_VOIDP: @@ -175,7 +195,7 @@ with_gvl_callback(void *ptr) case TYPE_LONG_LONG: *(LONG_LONG *)x->resp = NUM2LL(ret); break; - case -TYPE_LONG_LONG: + case TYPE_ULONG_LONG: *(unsigned LONG_LONG *)x->resp = NUM2ULL(ret); break; #endif @@ -183,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); } @@ -224,9 +251,27 @@ allocate(VALUE klass) return i; } +static fiddle_closure * +get_raw(VALUE self) +{ + fiddle_closure *closure; + TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure); + if (!closure) { + rb_raise(rb_eArgError, "already freed: %+"PRIsVALUE, self); + } + return closure; +} + +typedef struct { + VALUE self; + int argc; + VALUE *argv; +} initialize_data; + static VALUE -initialize(int rbargc, VALUE argv[], VALUE self) +initialize_body(VALUE user_data) { + initialize_data *data = (initialize_data *)user_data; VALUE ret; VALUE args; VALUE normalized_args; @@ -237,14 +282,14 @@ initialize(int rbargc, VALUE argv[], VALUE self) ffi_status result; int i, argc; - if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi)) - abi = INT2NUM(FFI_DEFAULT_ABI); + if (2 == rb_scan_args(data->argc, data->argv, "21", &ret, &args, &abi)) + abi = INT2NUM(FFI_DEFAULT_ABI); Check_Type(args, T_ARRAY); argc = RARRAY_LENINT(args); - TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl); + TypedData_Get_Struct(data->self, fiddle_closure, &closure_data_type, cl); cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *)); @@ -257,8 +302,8 @@ initialize(int rbargc, VALUE argv[], VALUE self) cl->argv[argc] = NULL; ret = rb_fiddle_type_ensure(ret); - rb_iv_set(self, "@ctype", ret); - rb_iv_set(self, "@args", normalized_args); + rb_iv_set(data->self, "@ctype", ret); + rb_iv_set(data->self, "@args", normalized_args); cif = &cl->cif; pcl = cl->pcl; @@ -269,38 +314,75 @@ initialize(int rbargc, VALUE argv[], VALUE self) rb_fiddle_int_to_ffi_type(NUM2INT(ret)), cl->argv); - if (FFI_OK != result) - rb_raise(rb_eRuntimeError, "error prepping CIF %d", result); + if (FFI_OK != result) { + rb_raise(rb_eRuntimeError, "error prepping CIF %d", result); + } #if USE_FFI_CLOSURE_ALLOC result = ffi_prep_closure_loc(pcl, cif, callback, - (void *)self, cl->code); + (void *)(data->self), cl->code); #else - result = ffi_prep_closure(pcl, cif, callback, (void *)self); + result = ffi_prep_closure(pcl, cif, callback, (void *)(data->self)); cl->code = (void *)pcl; i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC); if (i) { - rb_sys_fail("mprotect"); + rb_sys_fail("mprotect"); } #endif - if (FFI_OK != result) - rb_raise(rb_eRuntimeError, "error prepping closure %d", result); + if (FFI_OK != result) { + rb_raise(rb_eRuntimeError, "error prepping closure %d", result); + } - return self; + return data->self; } static VALUE -to_i(VALUE self) +initialize_rescue(VALUE user_data, VALUE exception) { - fiddle_closure * cl; - void *code; + initialize_data *data = (initialize_data *)user_data; + dealloc(RTYPEDDATA_DATA(data->self)); + RTYPEDDATA_DATA(data->self) = NULL; + rb_exc_raise(exception); + return data->self; +} + +static VALUE +initialize(int argc, VALUE *argv, VALUE self) +{ + initialize_data data; + data.self = self; + data.argc = argc; + data.argv = argv; + return rb_rescue(initialize_body, (VALUE)&data, + initialize_rescue, (VALUE)&data); +} - TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl); +static VALUE +to_i(VALUE self) +{ + fiddle_closure *closure = get_raw(self); + return PTR2NUM(closure->code); +} - code = cl->code; +static VALUE +closure_free(VALUE self) +{ + fiddle_closure *closure; + TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure); + if (closure) { + dealloc(closure); + RTYPEDDATA_DATA(self) = NULL; + } + return RUBY_Qnil; +} - return PTR2NUM(code); +static VALUE +closure_freed_p(VALUE self) +{ + fiddle_closure *closure; + TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure); + return closure ? RUBY_Qfalse : RUBY_Qtrue; } void @@ -353,8 +435,24 @@ Init_fiddle_closure(void) /* * Document-method: to_i * - * Returns the memory address for this closure + * Returns the memory address for this closure. */ rb_define_method(cFiddleClosure, "to_i", to_i, 0); + + /* + * Document-method: free + * + * Free this closure explicitly. You can't use this closure anymore. + * + * If this closure is already freed, this does nothing. + */ + rb_define_method(cFiddleClosure, "free", closure_free, 0); + + /* + * Document-method: freed? + * + * Whether this closure was freed explicitly. + */ + rb_define_method(cFiddleClosure, "freed?", closure_freed_p, 0); } /* vim: set noet sw=4 sts=4 */ diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c index 6e0ce36378..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,34 +230,38 @@ 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_CHAR: + case TYPE_UCHAR: dst->uchar = (unsigned char)NUM2UINT(*src); break; case TYPE_SHORT: dst->sshort = (unsigned short)NUM2INT(*src); break; - case -TYPE_SHORT: + case TYPE_USHORT: dst->sshort = (signed short)NUM2UINT(*src); break; case TYPE_INT: dst->sint = NUM2INT(*src); break; - case -TYPE_INT: + case TYPE_UINT: dst->uint = NUM2UINT(*src); break; case TYPE_LONG: dst->slong = NUM2LONG(*src); break; - case -TYPE_LONG: + case TYPE_ULONG: dst->ulong = NUM2ULONG(*src); break; #if HAVE_LONG_LONG case TYPE_LONG_LONG: dst->slong_long = NUM2LL(*src); break; - case -TYPE_LONG_LONG: + case TYPE_ULONG_LONG: dst->ulong_long = NUM2ULL(*src); break; #endif @@ -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; } } @@ -283,24 +323,24 @@ rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval) PTR2NUM((void *)retval.pointer)); case TYPE_CHAR: return INT2NUM((signed char)retval.fffi_sarg); - case -TYPE_CHAR: + case TYPE_UCHAR: return INT2NUM((unsigned char)retval.fffi_arg); case TYPE_SHORT: return INT2NUM((signed short)retval.fffi_sarg); - case -TYPE_SHORT: + case TYPE_USHORT: return INT2NUM((unsigned short)retval.fffi_arg); case TYPE_INT: return INT2NUM((signed int)retval.fffi_sarg); - case -TYPE_INT: + case TYPE_UINT: return UINT2NUM((unsigned int)retval.fffi_arg); case TYPE_LONG: return LONG2NUM(retval.slong); - case -TYPE_LONG: + case TYPE_ULONG: return ULONG2NUM(retval.ulong); #if HAVE_LONG_LONG case TYPE_LONG_LONG: return LL2NUM(retval.slong_long); - case -TYPE_LONG_LONG: + case TYPE_ULONG_LONG: return ULL2NUM(retval.ulong_long); #endif case TYPE_FLOAT: @@ -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 4d33d46d33..43b11ca780 100644 --- a/ext/fiddle/depend +++ b/ext/fiddle/depend @@ -67,6 +67,7 @@ closure.o: $(hdrdir)/ruby/backward/2/stdalign.h closure.o: $(hdrdir)/ruby/backward/2/stdarg.h closure.o: $(hdrdir)/ruby/defines.h closure.o: $(hdrdir)/ruby/intern.h +closure.o: $(hdrdir)/ruby/internal/abi.h closure.o: $(hdrdir)/ruby/internal/anyargs.h closure.o: $(hdrdir)/ruby/internal/arithmetic.h closure.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -104,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 @@ -163,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 @@ -194,12 +195,12 @@ 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 closure.o: $(hdrdir)/ruby/internal/stdalign.h closure.o: $(hdrdir)/ruby/internal/stdbool.h +closure.o: $(hdrdir)/ruby/internal/stdckdint.h closure.o: $(hdrdir)/ruby/internal/symbol.h closure.o: $(hdrdir)/ruby/internal/value.h closure.o: $(hdrdir)/ruby/internal/value_type.h @@ -231,6 +232,7 @@ conversions.o: $(hdrdir)/ruby/backward/2/stdalign.h conversions.o: $(hdrdir)/ruby/backward/2/stdarg.h conversions.o: $(hdrdir)/ruby/defines.h conversions.o: $(hdrdir)/ruby/intern.h +conversions.o: $(hdrdir)/ruby/internal/abi.h conversions.o: $(hdrdir)/ruby/internal/anyargs.h conversions.o: $(hdrdir)/ruby/internal/arithmetic.h conversions.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -268,6 +270,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 @@ -327,7 +330,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 @@ -358,12 +360,12 @@ 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 conversions.o: $(hdrdir)/ruby/internal/stdalign.h conversions.o: $(hdrdir)/ruby/internal/stdbool.h +conversions.o: $(hdrdir)/ruby/internal/stdckdint.h conversions.o: $(hdrdir)/ruby/internal/symbol.h conversions.o: $(hdrdir)/ruby/internal/value.h conversions.o: $(hdrdir)/ruby/internal/value_type.h @@ -394,6 +396,7 @@ fiddle.o: $(hdrdir)/ruby/backward/2/stdalign.h fiddle.o: $(hdrdir)/ruby/backward/2/stdarg.h fiddle.o: $(hdrdir)/ruby/defines.h fiddle.o: $(hdrdir)/ruby/intern.h +fiddle.o: $(hdrdir)/ruby/internal/abi.h fiddle.o: $(hdrdir)/ruby/internal/anyargs.h fiddle.o: $(hdrdir)/ruby/internal/arithmetic.h fiddle.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -431,6 +434,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 @@ -490,7 +494,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 @@ -521,12 +524,12 @@ 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 fiddle.o: $(hdrdir)/ruby/internal/stdalign.h fiddle.o: $(hdrdir)/ruby/internal/stdbool.h +fiddle.o: $(hdrdir)/ruby/internal/stdckdint.h fiddle.o: $(hdrdir)/ruby/internal/symbol.h fiddle.o: $(hdrdir)/ruby/internal/value.h fiddle.o: $(hdrdir)/ruby/internal/value_type.h @@ -557,6 +560,7 @@ function.o: $(hdrdir)/ruby/backward/2/stdalign.h function.o: $(hdrdir)/ruby/backward/2/stdarg.h function.o: $(hdrdir)/ruby/defines.h function.o: $(hdrdir)/ruby/intern.h +function.o: $(hdrdir)/ruby/internal/abi.h function.o: $(hdrdir)/ruby/internal/anyargs.h function.o: $(hdrdir)/ruby/internal/arithmetic.h function.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -594,6 +598,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 @@ -653,7 +658,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 @@ -684,12 +688,12 @@ 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 function.o: $(hdrdir)/ruby/internal/stdalign.h function.o: $(hdrdir)/ruby/internal/stdbool.h +function.o: $(hdrdir)/ruby/internal/stdckdint.h function.o: $(hdrdir)/ruby/internal/symbol.h function.o: $(hdrdir)/ruby/internal/value.h function.o: $(hdrdir)/ruby/internal/value_type.h @@ -721,6 +725,7 @@ handle.o: $(hdrdir)/ruby/backward/2/stdalign.h handle.o: $(hdrdir)/ruby/backward/2/stdarg.h handle.o: $(hdrdir)/ruby/defines.h handle.o: $(hdrdir)/ruby/intern.h +handle.o: $(hdrdir)/ruby/internal/abi.h handle.o: $(hdrdir)/ruby/internal/anyargs.h handle.o: $(hdrdir)/ruby/internal/arithmetic.h handle.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -758,6 +763,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 @@ -817,7 +823,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 @@ -848,12 +853,12 @@ 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 handle.o: $(hdrdir)/ruby/internal/stdalign.h handle.o: $(hdrdir)/ruby/internal/stdbool.h +handle.o: $(hdrdir)/ruby/internal/stdckdint.h handle.o: $(hdrdir)/ruby/internal/symbol.h handle.o: $(hdrdir)/ruby/internal/value.h handle.o: $(hdrdir)/ruby/internal/value_type.h @@ -885,6 +890,7 @@ memory_view.o: $(hdrdir)/ruby/backward/2/stdarg.h memory_view.o: $(hdrdir)/ruby/defines.h memory_view.o: $(hdrdir)/ruby/encoding.h memory_view.o: $(hdrdir)/ruby/intern.h +memory_view.o: $(hdrdir)/ruby/internal/abi.h memory_view.o: $(hdrdir)/ruby/internal/anyargs.h memory_view.o: $(hdrdir)/ruby/internal/arithmetic.h memory_view.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -922,6 +928,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 @@ -990,7 +997,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 @@ -1021,12 +1027,12 @@ 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 memory_view.o: $(hdrdir)/ruby/internal/stdalign.h memory_view.o: $(hdrdir)/ruby/internal/stdbool.h +memory_view.o: $(hdrdir)/ruby/internal/stdckdint.h memory_view.o: $(hdrdir)/ruby/internal/symbol.h memory_view.o: $(hdrdir)/ruby/internal/value.h memory_view.o: $(hdrdir)/ruby/internal/value_type.h @@ -1060,6 +1066,7 @@ pinned.o: $(hdrdir)/ruby/backward/2/stdalign.h pinned.o: $(hdrdir)/ruby/backward/2/stdarg.h pinned.o: $(hdrdir)/ruby/defines.h pinned.o: $(hdrdir)/ruby/intern.h +pinned.o: $(hdrdir)/ruby/internal/abi.h pinned.o: $(hdrdir)/ruby/internal/anyargs.h pinned.o: $(hdrdir)/ruby/internal/arithmetic.h pinned.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -1097,6 +1104,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 @@ -1156,7 +1164,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 @@ -1187,12 +1194,12 @@ 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 pinned.o: $(hdrdir)/ruby/internal/stdalign.h pinned.o: $(hdrdir)/ruby/internal/stdbool.h +pinned.o: $(hdrdir)/ruby/internal/stdckdint.h pinned.o: $(hdrdir)/ruby/internal/symbol.h pinned.o: $(hdrdir)/ruby/internal/value.h pinned.o: $(hdrdir)/ruby/internal/value_type.h @@ -1224,6 +1231,7 @@ pointer.o: $(hdrdir)/ruby/backward/2/stdarg.h pointer.o: $(hdrdir)/ruby/defines.h pointer.o: $(hdrdir)/ruby/encoding.h pointer.o: $(hdrdir)/ruby/intern.h +pointer.o: $(hdrdir)/ruby/internal/abi.h pointer.o: $(hdrdir)/ruby/internal/anyargs.h pointer.o: $(hdrdir)/ruby/internal/arithmetic.h pointer.o: $(hdrdir)/ruby/internal/arithmetic/char.h @@ -1261,6 +1269,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 @@ -1329,7 +1338,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 @@ -1360,12 +1368,12 @@ 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 pointer.o: $(hdrdir)/ruby/internal/stdalign.h pointer.o: $(hdrdir)/ruby/internal/stdbool.h +pointer.o: $(hdrdir)/ruby/internal/stdckdint.h pointer.o: $(hdrdir)/ruby/internal/symbol.h pointer.o: $(hdrdir)/ruby/internal/value.h pointer.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb index 053456d534..2d85b3eea5 100644 --- a/ext/fiddle/extconf.rb +++ b/ext/fiddle/extconf.rb @@ -46,7 +46,7 @@ end libffi_version = nil have_libffi = false -bundle = enable_config('bundled-libffi') +bundle = with_config("libffi-source-dir") unless bundle dir_config 'libffi' @@ -63,31 +63,20 @@ 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 unless have_libffi - # for https://github.com/ruby/fiddle - extlibs_rb = File.expand_path("../../bin/extlibs.rb", $srcdir) - if bundle && File.exist?(extlibs_rb) - require "fileutils" - require_relative "../../bin/extlibs" - extlibs = ExtLibs.new - cache_dir = File.expand_path("../../tmp/.download_cache", $srcdir) - ext_dir = File.expand_path("../../ext", $srcdir) - Dir.glob("#{$srcdir}/libffi-*/").each{|dir| FileUtils.rm_rf(dir)} - extlibs.run(["--cache=#{cache_dir}", ext_dir]) - end - if bundle != false - libffi_package_name = Dir.glob("#{$srcdir}/libffi-*/") - .map {|n| File.basename(n)} - .max_by {|n| n.scan(/\d+/).map(&:to_i)} - end - unless libffi_package_name - raise "missing libffi. Please install libffi." + if bundle + libffi_srcdir = libffi_package_name = bundle + else + raise "missing libffi. Please install libffi or use --with-libffi-source-dir with libffi source location." end - - libffi_srcdir = "#{$srcdir}/#{libffi_package_name}" ffi_header = 'ffi.h' libffi = Struct.new(*%I[dir srcdir builddir include lib a cflags ldflags opt arch]).new libffi.dir = libffi_package_name @@ -226,7 +215,7 @@ types.each do |type, signed| end if libffi - $LOCAL_LIBS.prepend("./#{libffi.a} ").strip! # to exts.mk + $LOCAL_LIBS.prepend("#{libffi.a} ").strip! # to exts.mk $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)') end create_makefile 'fiddle' do |conf| diff --git a/ext/fiddle/extlibs b/ext/fiddle/extlibs deleted file mode 100644 index 68dac46a95..0000000000 --- a/ext/fiddle/extlibs +++ /dev/null @@ -1,13 +0,0 @@ -ver = 3.2.1 -pkg = libffi-$(ver) - -https://ftp.osuosl.org/pub/blfs/conglomeration/libffi/$(pkg).tar.gz \ - md5:83b89587607e3eb65c70d361f13bab43 \ - sha512:980ca30a8d76f963fca722432b1fe5af77d7a4e4d2eac5144fbc5374d4c596609a293440573f4294207e1bdd9fda80ad1e1cafb2ffb543df5a275bc3bd546483 \ - # - win32/$(pkg)-mswin.patch -p0 - -$(pkg)/config.guess -> /tool/config.guess -$(pkg)/config.sub -> /tool/config.sub - -! chdir: $(pkg)| autoconf || exit 0 diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c index a8b5123269..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. + * + * Example: * - * Fiddle.dlwrap(lib['strcpy'].to_s(16)) - * => 25522520 + * Fiddle.dlwrap(123) + * # => 247 */ static VALUE rb_fiddle_value2ptr(VALUE self, VALUE val) @@ -164,137 +171,199 @@ Init_fiddle(void) */ rb_eFiddleDLError = rb_define_class_under(mFiddle, "DLError", rb_eFiddleError); - /* Document-const: TYPE_VOID + VALUE mFiddleTypes = rb_define_module_under(mFiddle, "Types"); + + /* Document-const: Fiddle::Types::VOID * * C type - void */ - rb_define_const(mFiddle, "TYPE_VOID", INT2NUM(TYPE_VOID)); + rb_define_const(mFiddleTypes, "VOID", INT2NUM(TYPE_VOID)); - /* Document-const: TYPE_VOIDP + /* Document-const: Fiddle::Types::VOIDP * * C type - void* */ - rb_define_const(mFiddle, "TYPE_VOIDP", INT2NUM(TYPE_VOIDP)); + rb_define_const(mFiddleTypes, "VOIDP", INT2NUM(TYPE_VOIDP)); - /* Document-const: TYPE_CHAR + /* Document-const: Fiddle::Types::CHAR * * C type - char */ - rb_define_const(mFiddle, "TYPE_CHAR", INT2NUM(TYPE_CHAR)); + rb_define_const(mFiddleTypes, "CHAR", INT2NUM(TYPE_CHAR)); - /* Document-const: TYPE_SHORT + /* Document-const: Fiddle::Types::UCHAR + * + * C type - unsigned char + */ + rb_define_const(mFiddleTypes, "UCHAR", INT2NUM(TYPE_UCHAR)); + + /* Document-const: Fiddle::Types::SHORT * * C type - short */ - rb_define_const(mFiddle, "TYPE_SHORT", INT2NUM(TYPE_SHORT)); + rb_define_const(mFiddleTypes, "SHORT", INT2NUM(TYPE_SHORT)); - /* Document-const: TYPE_INT + /* Document-const: Fiddle::Types::USHORT + * + * C type - unsigned short + */ + rb_define_const(mFiddleTypes, "USHORT", INT2NUM(TYPE_USHORT)); + + /* Document-const: Fiddle::Types::INT * * C type - int */ - rb_define_const(mFiddle, "TYPE_INT", INT2NUM(TYPE_INT)); + rb_define_const(mFiddleTypes, "INT", INT2NUM(TYPE_INT)); + + /* Document-const: Fiddle::Types::UINT + * + * C type - unsigned int + */ + rb_define_const(mFiddleTypes, "UINT", INT2NUM(TYPE_UINT)); - /* Document-const: TYPE_LONG + /* Document-const: Fiddle::Types::LONG * * C type - long */ - rb_define_const(mFiddle, "TYPE_LONG", INT2NUM(TYPE_LONG)); + rb_define_const(mFiddleTypes, "LONG", INT2NUM(TYPE_LONG)); + + /* Document-const: Fiddle::Types::ULONG + * + * C type - long + */ + rb_define_const(mFiddleTypes, "ULONG", INT2NUM(TYPE_ULONG)); #if HAVE_LONG_LONG - /* Document-const: TYPE_LONG_LONG + /* Document-const: Fiddle::Types::LONG_LONG + * + * C type - long long + */ + rb_define_const(mFiddleTypes, "LONG_LONG", INT2NUM(TYPE_LONG_LONG)); + + /* Document-const: Fiddle::Types::ULONG_LONG * * C type - long long */ - rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG)); + rb_define_const(mFiddleTypes, "ULONG_LONG", INT2NUM(TYPE_ULONG_LONG)); #endif #ifdef TYPE_INT8_T - /* Document-const: TYPE_INT8_T + /* Document-const: Fiddle::Types::INT8_T * * C type - int8_t */ - rb_define_const(mFiddle, "TYPE_INT8_T", INT2NUM(TYPE_INT8_T)); + rb_define_const(mFiddleTypes, "INT8_T", INT2NUM(TYPE_INT8_T)); + + /* Document-const: Fiddle::Types::UINT8_T + * + * C type - uint8_t + */ + rb_define_const(mFiddleTypes, "UINT8_T", INT2NUM(TYPE_UINT8_T)); #endif #ifdef TYPE_INT16_T - /* Document-const: TYPE_INT16_T + /* Document-const: Fiddle::Types::INT16_T * * C type - int16_t */ - rb_define_const(mFiddle, "TYPE_INT16_T", INT2NUM(TYPE_INT16_T)); + rb_define_const(mFiddleTypes, "INT16_T", INT2NUM(TYPE_INT16_T)); + + /* Document-const: Fiddle::Types::UINT16_T + * + * C type - uint16_t + */ + rb_define_const(mFiddleTypes, "UINT16_T", INT2NUM(TYPE_UINT16_T)); #endif #ifdef TYPE_INT32_T - /* Document-const: TYPE_INT32_T + /* Document-const: Fiddle::Types::INT32_T * * C type - int32_t */ - rb_define_const(mFiddle, "TYPE_INT32_T", INT2NUM(TYPE_INT32_T)); + rb_define_const(mFiddleTypes, "INT32_T", INT2NUM(TYPE_INT32_T)); + + /* Document-const: Fiddle::Types::UINT32_T + * + * C type - uint32_t + */ + rb_define_const(mFiddleTypes, "UINT32_T", INT2NUM(TYPE_UINT32_T)); #endif #ifdef TYPE_INT64_T - /* Document-const: TYPE_INT64_T + /* Document-const: Fiddle::Types::INT64_T * * C type - int64_t */ - rb_define_const(mFiddle, "TYPE_INT64_T", INT2NUM(TYPE_INT64_T)); + rb_define_const(mFiddleTypes, "INT64_T", INT2NUM(TYPE_INT64_T)); + + /* Document-const: Fiddle::Types::UINT64_T + * + * C type - uint64_t + */ + rb_define_const(mFiddleTypes, "UINT64_T", INT2NUM(TYPE_UINT64_T)); #endif - /* Document-const: TYPE_FLOAT + /* Document-const: Fiddle::Types::FLOAT * * C type - float */ - rb_define_const(mFiddle, "TYPE_FLOAT", INT2NUM(TYPE_FLOAT)); + rb_define_const(mFiddleTypes, "FLOAT", INT2NUM(TYPE_FLOAT)); - /* Document-const: TYPE_DOUBLE + /* Document-const: Fiddle::Types::DOUBLE * * C type - double */ - rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE)); + rb_define_const(mFiddleTypes, "DOUBLE", INT2NUM(TYPE_DOUBLE)); #ifdef HAVE_FFI_PREP_CIF_VAR - /* Document-const: TYPE_VARIADIC + /* Document-const: Fiddle::Types::VARIADIC * * C type - ... */ - rb_define_const(mFiddle, "TYPE_VARIADIC", INT2NUM(TYPE_VARIADIC)); + rb_define_const(mFiddleTypes, "VARIADIC", INT2NUM(TYPE_VARIADIC)); #endif - /* Document-const: TYPE_CONST_STRING + /* Document-const: Fiddle::Types::CONST_STRING * * C type - const char* ('\0' terminated const char*) */ - rb_define_const(mFiddle, "TYPE_CONST_STRING", INT2NUM(TYPE_CONST_STRING)); + rb_define_const(mFiddleTypes, "CONST_STRING", INT2NUM(TYPE_CONST_STRING)); - /* Document-const: TYPE_SIZE_T + /* Document-const: Fiddle::Types::SIZE_T * * C type - size_t */ - rb_define_const(mFiddle, "TYPE_SIZE_T", INT2NUM(TYPE_SIZE_T)); + rb_define_const(mFiddleTypes, "SIZE_T", INT2NUM(TYPE_SIZE_T)); - /* Document-const: TYPE_SSIZE_T + /* Document-const: Fiddle::Types::SSIZE_T * * C type - ssize_t */ - rb_define_const(mFiddle, "TYPE_SSIZE_T", INT2NUM(TYPE_SSIZE_T)); + rb_define_const(mFiddleTypes, "SSIZE_T", INT2NUM(TYPE_SSIZE_T)); - /* Document-const: TYPE_PTRDIFF_T + /* Document-const: Fiddle::Types::PTRDIFF_T * * C type - ptrdiff_t */ - rb_define_const(mFiddle, "TYPE_PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T)); + rb_define_const(mFiddleTypes, "PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T)); - /* Document-const: TYPE_INTPTR_T + /* Document-const: Fiddle::Types::INTPTR_T * * C type - intptr_t */ - rb_define_const(mFiddle, "TYPE_INTPTR_T", INT2NUM(TYPE_INTPTR_T)); + rb_define_const(mFiddleTypes, "INTPTR_T", INT2NUM(TYPE_INTPTR_T)); - /* Document-const: TYPE_UINTPTR_T + /* Document-const: Fiddle::Types::UINTPTR_T * * C type - uintptr_t */ - rb_define_const(mFiddle, "TYPE_UINTPTR_T", INT2NUM(TYPE_UINTPTR_T)); + 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 * @@ -400,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 @@ -422,30 +497,60 @@ Init_fiddle(void) */ rb_define_const(mFiddle, "SIZEOF_CHAR", INT2NUM(sizeof(char))); + /* Document-const: SIZEOF_UCHAR + * + * size of a unsigned char + */ + rb_define_const(mFiddle, "SIZEOF_UCHAR", INT2NUM(sizeof(unsigned char))); + /* Document-const: SIZEOF_SHORT * * size of a short */ rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short))); + /* Document-const: SIZEOF_USHORT + * + * size of a unsigned short + */ + rb_define_const(mFiddle, "SIZEOF_USHORT", INT2NUM(sizeof(unsigned short))); + /* Document-const: SIZEOF_INT * * size of an int */ rb_define_const(mFiddle, "SIZEOF_INT", INT2NUM(sizeof(int))); + /* Document-const: SIZEOF_UINT + * + * size of an unsigned int + */ + rb_define_const(mFiddle, "SIZEOF_UINT", INT2NUM(sizeof(unsigned int))); + /* Document-const: SIZEOF_LONG * * size of a long */ rb_define_const(mFiddle, "SIZEOF_LONG", INT2NUM(sizeof(long))); + /* Document-const: SIZEOF_ULONG + * + * size of a unsigned long + */ + rb_define_const(mFiddle, "SIZEOF_ULONG", INT2NUM(sizeof(unsigned long))); + #if HAVE_LONG_LONG /* Document-const: SIZEOF_LONG_LONG * * size of a long long */ rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG))); + + /* Document-const: SIZEOF_ULONG_LONG + * + * size of a unsigned long long + */ + rb_define_const(mFiddle, "SIZEOF_ULONG_LONG", INT2NUM(sizeof(unsigned LONG_LONG))); #endif /* Document-const: SIZEOF_INT8_T @@ -454,24 +559,48 @@ Init_fiddle(void) */ rb_define_const(mFiddle, "SIZEOF_INT8_T", INT2NUM(sizeof(int8_t))); + /* Document-const: SIZEOF_UINT8_T + * + * size of a uint8_t + */ + rb_define_const(mFiddle, "SIZEOF_UINT8_T", INT2NUM(sizeof(uint8_t))); + /* Document-const: SIZEOF_INT16_T * * size of a int16_t */ rb_define_const(mFiddle, "SIZEOF_INT16_T", INT2NUM(sizeof(int16_t))); + /* Document-const: SIZEOF_UINT16_T + * + * size of a uint16_t + */ + rb_define_const(mFiddle, "SIZEOF_UINT16_T", INT2NUM(sizeof(uint16_t))); + /* Document-const: SIZEOF_INT32_T * * size of a int32_t */ rb_define_const(mFiddle, "SIZEOF_INT32_T", INT2NUM(sizeof(int32_t))); + /* Document-const: SIZEOF_UINT32_T + * + * size of a uint32_t + */ + rb_define_const(mFiddle, "SIZEOF_UINT32_T", INT2NUM(sizeof(uint32_t))); + /* Document-const: SIZEOF_INT64_T * * size of a int64_t */ rb_define_const(mFiddle, "SIZEOF_INT64_T", INT2NUM(sizeof(int64_t))); + /* Document-const: SIZEOF_UINT64_T + * + * size of a uint64_t + */ + rb_define_const(mFiddle, "SIZEOF_UINT64_T", INT2NUM(sizeof(uint64_t))); + /* Document-const: SIZEOF_FLOAT * * size of a float @@ -520,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 @@ -540,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 a9c0ec4026..3a1072dd49 100644 --- a/ext/fiddle/fiddle.gemspec +++ b/ext/fiddle/fiddle.gemspec @@ -20,15 +20,12 @@ Gem::Specification.new do |spec| "LICENSE.txt", "README.md", "Rakefile", - "bin/downloader.rb", - "bin/extlibs.rb", "ext/fiddle/closure.c", "ext/fiddle/closure.h", "ext/fiddle/conversions.c", "ext/fiddle/conversions.h", "ext/fiddle/depend", "ext/fiddle/extconf.rb", - "ext/fiddle/extlibs", "ext/fiddle/fiddle.c", "ext/fiddle/fiddle.h", "ext/fiddle/function.c", @@ -59,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 9de62a58cc..348baa9ab9 100644 --- a/ext/fiddle/fiddle.h +++ b/ext/fiddle/fiddle.h @@ -111,23 +111,36 @@ #define TYPE_VOID 0 #define TYPE_VOIDP 1 #define TYPE_CHAR 2 +#define TYPE_UCHAR -TYPE_CHAR #define TYPE_SHORT 3 +#define TYPE_USHORT -TYPE_SHORT #define TYPE_INT 4 +#define TYPE_UINT -TYPE_INT #define TYPE_LONG 5 -#if HAVE_LONG_LONG +#define TYPE_ULONG -TYPE_LONG +#ifdef HAVE_LONG_LONG #define TYPE_LONG_LONG 6 +#define TYPE_ULONG_LONG -TYPE_LONG_LONG #endif #define TYPE_FLOAT 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 + #if SIZEOF_SHORT == 2 # define TYPE_INT16_T TYPE_SHORT #elif SIZEOF_INT == 2 # define TYPE_INT16_T TYPE_INT #endif + +#ifdef TYPE_INT16_T +# define TYPE_UINT16_T -TYPE_INT16_T +#endif + #if SIZEOF_SHORT == 4 # define TYPE_INT32_T TYPE_SHORT #elif SIZEOF_INT == 4 @@ -135,6 +148,11 @@ #elif SIZEOF_LONG == 4 # define TYPE_INT32_T TYPE_LONG #endif + +#ifdef TYPE_INT32_T +#define TYPE_UINT32_T -TYPE_INT32_T +#endif + #if SIZEOF_INT == 8 # define TYPE_INT64_T TYPE_INT #elif SIZEOF_LONG == 8 @@ -143,6 +161,10 @@ # define TYPE_INT64_T TYPE_LONG_LONG #endif +#ifdef TYPE_INT64_T +#define TYPE_UINT64_T -TYPE_INT64_T +#endif + #ifndef TYPE_SSIZE_T # if SIZEOF_SIZE_T == SIZEOF_INT # define TYPE_SSIZE_T TYPE_INT @@ -175,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 76b90909d3..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, }; /* @@ -321,8 +326,10 @@ rb_fiddle_handle_s_sym(VALUE self, VALUE sym) return fiddle_handle_sym(RTLD_NEXT, sym); } -static VALUE -fiddle_handle_sym(void *handle, VALUE symbol) +typedef void (*fiddle_void_func)(void); + +static fiddle_void_func +fiddle_handle_find_func(void *handle, VALUE symbol) { #if defined(HAVE_DLERROR) const char *err; @@ -330,13 +337,13 @@ fiddle_handle_sym(void *handle, VALUE symbol) #else # define CHECK_DLERROR #endif - void (*func)(); + fiddle_void_func func; const char *name = StringValueCStr(symbol); #ifdef HAVE_DLERROR dlerror(); #endif - func = (void (*)())(VALUE)dlsym(handle, name); + func = (fiddle_void_func)(VALUE)dlsym(handle, name); CHECK_DLERROR; #if defined(FUNC_STDCALL) if( !func ){ @@ -379,6 +386,53 @@ fiddle_handle_sym(void *handle, VALUE symbol) xfree(name_n); } #endif + + return func; +} + +static VALUE +rb_fiddle_handle_s_sym_defined(VALUE self, VALUE sym) +{ + fiddle_void_func func; + + func = fiddle_handle_find_func(RTLD_NEXT, sym); + + if( func ) { + return PTR2NUM(func); + } + else { + return Qnil; + } +} + +static VALUE +rb_fiddle_handle_sym_defined(VALUE self, VALUE sym) +{ + struct dl_handle *fiddle_handle; + fiddle_void_func func; + + TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); + if( ! fiddle_handle->open ){ + rb_raise(rb_eFiddleDLError, "closed handle"); + } + + func = fiddle_handle_find_func(fiddle_handle->ptr, sym); + + if( func ) { + return PTR2NUM(func); + } + else { + return Qnil; + } +} + +static VALUE +fiddle_handle_sym(void *handle, VALUE symbol) +{ + fiddle_void_func func; + + func = fiddle_handle_find_func(handle, symbol); + if( !func ){ rb_raise(rb_eFiddleDLError, "unknown symbol \"%"PRIsVALUE"\"", symbol); } @@ -468,6 +522,7 @@ Init_fiddle_handle(void) rb_cHandle = rb_define_class_under(mFiddle, "Handle", rb_cObject); rb_define_alloc_func(rb_cHandle, rb_fiddle_handle_s_allocate); rb_define_singleton_method(rb_cHandle, "sym", rb_fiddle_handle_s_sym, 1); + rb_define_singleton_method(rb_cHandle, "sym_defined?", rb_fiddle_handle_s_sym_defined, 1); rb_define_singleton_method(rb_cHandle, "[]", rb_fiddle_handle_s_sym, 1); /* Document-const: NEXT @@ -526,6 +581,7 @@ Init_fiddle_handle(void) rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 0); rb_define_method(rb_cHandle, "sym", rb_fiddle_handle_sym, 1); rb_define_method(rb_cHandle, "[]", rb_fiddle_handle_sym, 1); + rb_define_method(rb_cHandle, "sym_defined?", rb_fiddle_handle_sym_defined, 1); rb_define_method(rb_cHandle, "file_name", rb_fiddle_handle_file_name, 0); rb_define_method(rb_cHandle, "disable_close", rb_fiddle_handle_disable_close, 0); rb_define_method(rb_cHandle, "enable_close", rb_fiddle_handle_enable_close, 0); diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb index 4512989310..6137c487c6 100644 --- a/ext/fiddle/lib/fiddle.rb +++ b/ext/fiddle/lib/fiddle.rb @@ -58,7 +58,36 @@ module Fiddle # # See Fiddle::Handle.new for more. def dlopen library - Fiddle::Handle.new library + begin + Fiddle::Handle.new(library) + rescue DLError => error + case RUBY_PLATFORM + when /linux/ + case error.message + when /\A(\/.+?): (?:invalid ELF header|file too short)/ + # This may be a linker script: + # https://sourceware.org/binutils/docs/ld.html#Scripts + path = $1 + else + raise + end + else + raise + end + + File.open(path) do |input| + input.each_line do |line| + case line + when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/ + # TODO: Should we support multiple files? + return dlopen($1) + end + end + end + + # Not found + raise + end end module_function :dlopen @@ -67,4 +96,8 @@ module Fiddle RTLD_GLOBAL = Handle::RTLD_GLOBAL # :nodoc: RTLD_LAZY = Handle::RTLD_LAZY # :nodoc: RTLD_NOW = Handle::RTLD_NOW # :nodoc: + + Fiddle::Types.constants.each do |type| + const_set "TYPE_#{type}", Fiddle::Types.const_get(type) + end end diff --git a/ext/fiddle/lib/fiddle/closure.rb b/ext/fiddle/lib/fiddle/closure.rb index c865a63c20..7e0077ea52 100644 --- a/ext/fiddle/lib/fiddle/closure.rb +++ b/ext/fiddle/lib/fiddle/closure.rb @@ -1,6 +1,31 @@ # frozen_string_literal: true module Fiddle class Closure + class << self + # Create a new closure. If a block is given, the created closure + # is automatically freed after the given block is executed. + # + # The all given arguments are passed to Fiddle::Closure.new. So + # using this method without block equals to Fiddle::Closure.new. + # + # == Example + # + # Fiddle::Closure.create(TYPE_INT, [TYPE_INT]) do |closure| + # # closure is freed automatically when this block is finished. + # end + def create(*args) + if block_given? + closure = new(*args) + begin + yield(closure) + ensure + closure.free + end + else + new(*args) + end + end + end # the C type of the return of the FFI closure attr_reader :ctype diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb index 93a05513c9..264ca166dd 100644 --- a/ext/fiddle/lib/fiddle/cparser.rb +++ b/ext/fiddle/lib/fiddle/cparser.rb @@ -164,23 +164,35 @@ module Fiddle unless Fiddle.const_defined?(:TYPE_LONG_LONG) raise(RuntimeError, "unsupported type: #{ty}") end - return -TYPE_LONG_LONG - when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/ + return TYPE_ULONG_LONG + 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+long(?:\s+int\s+)?(?:\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_INT - 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_SHORT + return TYPE_UINT when /\A(?:signed\s+)?char(?:\s+\w+)?\z/ return TYPE_CHAR when /\Aunsigned\s+char(?:\s+\w+)?\z/ - return -TYPE_CHAR + return TYPE_UCHAR when /\Aint8_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT8_T) raise(RuntimeError, "unsupported type: #{ty}") @@ -190,7 +202,7 @@ module Fiddle unless Fiddle.const_defined?(:TYPE_INT8_T) raise(RuntimeError, "unsupported type: #{ty}") end - return -TYPE_INT8_T + return TYPE_UINT8_T when /\Aint16_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT16_T) raise(RuntimeError, "unsupported type: #{ty}") @@ -200,7 +212,7 @@ module Fiddle unless Fiddle.const_defined?(:TYPE_INT16_T) raise(RuntimeError, "unsupported type: #{ty}") end - return -TYPE_INT16_T + return TYPE_UINT16_T when /\Aint32_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT32_T) raise(RuntimeError, "unsupported type: #{ty}") @@ -210,7 +222,7 @@ module Fiddle unless Fiddle.const_defined?(:TYPE_INT32_T) raise(RuntimeError, "unsupported type: #{ty}") end - return -TYPE_INT32_T + return TYPE_UINT32_T when /\Aint64_t(?:\s+\w+)?\z/ unless Fiddle.const_defined?(:TYPE_INT64_T) raise(RuntimeError, "unsupported type: #{ty}") @@ -220,7 +232,7 @@ module Fiddle unless Fiddle.const_defined?(:TYPE_INT64_T) raise(RuntimeError, "unsupported type: #{ty}") end - return -TYPE_INT64_T + return TYPE_UINT64_T when /\Afloat(?:\s+\w+)?\z/ return TYPE_FLOAT when /\Adouble(?:\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 22eccedb76..81088f402b 100644 --- a/ext/fiddle/lib/fiddle/pack.rb +++ b/ext/fiddle/lib/fiddle/pack.rb @@ -11,25 +11,36 @@ module Fiddle TYPE_LONG => ALIGN_LONG, TYPE_FLOAT => ALIGN_FLOAT, TYPE_DOUBLE => ALIGN_DOUBLE, - -TYPE_CHAR => ALIGN_CHAR, - -TYPE_SHORT => ALIGN_SHORT, - -TYPE_INT => ALIGN_INT, - -TYPE_LONG => ALIGN_LONG, + TYPE_UCHAR => ALIGN_CHAR, + TYPE_USHORT => ALIGN_SHORT, + TYPE_UINT => ALIGN_INT, + TYPE_ULONG => ALIGN_LONG, + TYPE_BOOL => ALIGN_BOOL, } PACK_MAP = { - TYPE_VOIDP => "l!", + TYPE_VOIDP => "L!", TYPE_CHAR => "c", TYPE_SHORT => "s!", TYPE_INT => "i!", TYPE_LONG => "l!", TYPE_FLOAT => "f", TYPE_DOUBLE => "d", - -TYPE_CHAR => "c", - -TYPE_SHORT => "s!", - -TYPE_INT => "i!", - -TYPE_LONG => "l!", + TYPE_UCHAR => "C", + TYPE_USHORT => "S!", + 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, @@ -39,16 +50,18 @@ module Fiddle TYPE_LONG => SIZEOF_LONG, TYPE_FLOAT => SIZEOF_FLOAT, TYPE_DOUBLE => SIZEOF_DOUBLE, - -TYPE_CHAR => SIZEOF_CHAR, - -TYPE_SHORT => SIZEOF_SHORT, - -TYPE_INT => SIZEOF_INT, - -TYPE_LONG => SIZEOF_LONG, + TYPE_UCHAR => SIZEOF_CHAR, + 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_LONG_LONG] = ALIGN_LONG_LONG - PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q" - SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG - PACK_MAP[TYPE_VOIDP] = "q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP + ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[TYPE_ULONG_LONG] = ALIGN_LONG_LONG + PACK_MAP[TYPE_LONG_LONG] = "q" + PACK_MAP[TYPE_ULONG_LONG] = "Q" + SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[TYPE_ULONG_LONG] = SIZEOF_LONG_LONG + PACK_MAP[TYPE_VOIDP] = "Q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP end def align(addr, align) 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 db6504b650..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.0" + 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) |