diff options
42 files changed, 1 insertions, 11366 deletions
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c deleted file mode 100644 index d526d870e8..0000000000 --- a/ext/fiddle/closure.c +++ /dev/null @@ -1,458 +0,0 @@ -#include <fiddle.h> -#include <stdbool.h> -#include <ruby/thread.h> - -int ruby_thread_has_gvl_p(void); /* from internal.h */ - -VALUE cFiddleClosure; - -typedef struct { - void * code; - ffi_closure *pcl; - ffi_cif cif; - int argc; - ffi_type **argv; -} fiddle_closure; - -#if defined(__OpenBSD__) -# define USE_FFI_CLOSURE_ALLOC 0 -#endif - -#if defined(USE_FFI_CLOSURE_ALLOC) -#elif !defined(HAVE_FFI_CLOSURE_ALLOC) -# define USE_FFI_CLOSURE_ALLOC 0 -#else -# define USE_FFI_CLOSURE_ALLOC 1 -#endif - -static void -dealloc(void * ptr) -{ - fiddle_closure * cls = (fiddle_closure *)ptr; -#if USE_FFI_CLOSURE_ALLOC - ffi_closure_free(cls->pcl); -#else - munmap(cls->pcl, sizeof(*cls->pcl)); -#endif - if (cls->argv) xfree(cls->argv); - xfree(cls); -} - -static size_t -closure_memsize(const void * ptr) -{ - fiddle_closure * cls = (fiddle_closure *)ptr; - size_t size = 0; - - size += sizeof(*cls); -#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API - size += ffi_raw_size(&cls->cif); -#endif - size += sizeof(*cls->argv); - size += sizeof(ffi_closure); - - return size; -} - -const rb_data_type_t closure_data_type = { - .wrap_struct_name = "fiddle/closure", - .function = { - .dmark = 0, - .dfree = dealloc, - .dsize = closure_memsize - }, - .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, -}; - -struct callback_args { - ffi_cif *cif; - void *resp; - void **args; - void *ctx; -}; - -static void * -with_gvl_callback(void *ptr) -{ - struct callback_args *x = ptr; - - VALUE self = (VALUE)x->ctx; - VALUE rbargs = rb_iv_get(self, "@args"); - VALUE ctype = rb_iv_get(self, "@ctype"); - int argc = RARRAY_LENINT(rbargs); - VALUE params = rb_ary_tmp_new(argc); - VALUE ret; - VALUE cPointer; - int i, type; - - cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - - for (i = 0; i < argc; i++) { - type = NUM2INT(RARRAY_AREF(rbargs, i)); - switch (type) { - case TYPE_VOID: - argc = 0; - break; - case TYPE_INT: - rb_ary_push(params, INT2NUM(*(int *)x->args[i])); - break; - case TYPE_UINT: - rb_ary_push(params, UINT2NUM(*(unsigned int *)x->args[i])); - break; - case TYPE_VOIDP: - rb_ary_push(params, - rb_funcall(cPointer, rb_intern("[]"), 1, - PTR2NUM(*(void **)x->args[i]))); - break; - case TYPE_LONG: - rb_ary_push(params, LONG2NUM(*(long *)x->args[i])); - break; - 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_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_USHORT: - rb_ary_push(params, UINT2NUM(*(unsigned short *)x->args[i])); - break; - case TYPE_DOUBLE: - rb_ary_push(params, rb_float_new(*(double *)x->args[i])); - break; - case TYPE_FLOAT: - rb_ary_push(params, rb_float_new(*(float *)x->args[i])); - break; -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - rb_ary_push(params, LL2NUM(*(LONG_LONG *)x->args[i])); - break; - case TYPE_ULONG_LONG: - rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)x->args[i])); - break; -#endif - case TYPE_CONST_STRING: - 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); - } - } - - ret = rb_funcall2(self, rb_intern("call"), argc, RARRAY_CONST_PTR(params)); - RB_GC_GUARD(params); - - type = NUM2INT(ctype); - switch (type) { - case TYPE_VOID: - break; - case TYPE_LONG: - *(long *)x->resp = NUM2LONG(ret); - break; - case TYPE_ULONG: - *(unsigned long *)x->resp = NUM2ULONG(ret); - break; - case TYPE_CHAR: - case TYPE_SHORT: - case TYPE_INT: - *(ffi_sarg *)x->resp = NUM2INT(ret); - break; - case TYPE_UCHAR: - case TYPE_USHORT: - case TYPE_UINT: - *(ffi_arg *)x->resp = NUM2UINT(ret); - break; - case TYPE_VOIDP: - *(void **)x->resp = NUM2PTR(ret); - break; - case TYPE_DOUBLE: - *(double *)x->resp = NUM2DBL(ret); - break; - case TYPE_FLOAT: - *(float *)x->resp = (float)NUM2DBL(ret); - break; -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - *(LONG_LONG *)x->resp = NUM2LL(ret); - break; - case TYPE_ULONG_LONG: - *(unsigned LONG_LONG *)x->resp = NUM2ULL(ret); - break; -#endif - case TYPE_CONST_STRING: - /* 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); - } - return 0; -} - -static void -callback(ffi_cif *cif, void *resp, void **args, void *ctx) -{ - struct callback_args x; - - x.cif = cif; - x.resp = resp; - x.args = args; - x.ctx = ctx; - - if (ruby_thread_has_gvl_p()) { - (void)with_gvl_callback(&x); - } else { - (void)rb_thread_call_with_gvl(with_gvl_callback, &x); - } -} - -static VALUE -allocate(VALUE klass) -{ - fiddle_closure * closure; - - VALUE i = TypedData_Make_Struct(klass, fiddle_closure, - &closure_data_type, closure); - -#if USE_FFI_CLOSURE_ALLOC - closure->pcl = ffi_closure_alloc(sizeof(ffi_closure), &closure->code); -#else - closure->pcl = mmap(NULL, sizeof(ffi_closure), PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, -1, 0); -#endif - - 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_body(VALUE user_data) -{ - initialize_data *data = (initialize_data *)user_data; - VALUE ret; - VALUE args; - VALUE normalized_args; - VALUE abi; - fiddle_closure * cl; - ffi_cif * cif; - ffi_closure *pcl; - ffi_status result; - int i, argc; - - 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(data->self, fiddle_closure, &closure_data_type, cl); - - cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *)); - - normalized_args = rb_ary_new_capa(argc); - for (i = 0; i < argc; i++) { - VALUE arg = rb_fiddle_type_ensure(RARRAY_AREF(args, i)); - rb_ary_push(normalized_args, arg); - cl->argv[i] = rb_fiddle_int_to_ffi_type(NUM2INT(arg)); - } - cl->argv[argc] = NULL; - OBJ_FREEZE_RAW(normalized_args); - - ret = rb_fiddle_type_ensure(ret); - rb_iv_set(data->self, "@ctype", ret); - rb_iv_set(data->self, "@args", normalized_args); - - cif = &cl->cif; - pcl = cl->pcl; - - result = ffi_prep_cif(cif, - NUM2INT(abi), - argc, - rb_fiddle_int_to_ffi_type(NUM2INT(ret)), - cl->argv); - - 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 *)(data->self), cl->code); -#else - 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"); - } -#endif - - if (FFI_OK != result) { - rb_raise(rb_eRuntimeError, "error prepping closure %d", result); - } - - return data->self; -} - -static VALUE -initialize_rescue(VALUE user_data, VALUE exception) -{ - 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); -} - -static VALUE -to_i(VALUE self) -{ - fiddle_closure *closure = get_raw(self); - return PTR2NUM(closure->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; -} - -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 -Init_fiddle_closure(void) -{ -#if 0 - mFiddle = rb_define_module("Fiddle"); /* let rdoc know about mFiddle */ -#endif - - /* - * Document-class: Fiddle::Closure - * - * == Description - * - * An FFI closure wrapper, for handling callbacks. - * - * == Example - * - * closure = Class.new(Fiddle::Closure) { - * def call - * 10 - * end - * }.new(Fiddle::TYPE_INT, []) - * #=> #<#<Class:0x0000000150d308>:0x0000000150d240> - * func = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT) - * #=> #<Fiddle::Function:0x00000001516e58> - * func.call - * #=> 10 - */ - cFiddleClosure = rb_define_class_under(mFiddle, "Closure", rb_cObject); - - rb_define_alloc_func(cFiddleClosure, allocate); - - /* - * Document-method: new - * - * call-seq: new(ret, args, abi = Fiddle::DEFAULT) - * - * Construct a new Closure object. - * - * * +ret+ is the C type to be returned - * * +args+ is an Array of arguments, passed to the callback function - * * +abi+ is the abi of the closure - * - * If there is an error in preparing the ffi_cif or ffi_prep_closure, - * then a RuntimeError will be raised. - */ - rb_define_method(cFiddleClosure, "initialize", initialize, -1); - - /* - * Document-method: to_i - * - * 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); -} diff --git a/ext/fiddle/closure.h b/ext/fiddle/closure.h deleted file mode 100644 index d0a8be6180..0000000000 --- a/ext/fiddle/closure.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FIDDLE_CLOSURE_H -#define FIDDLE_CLOSURE_H - -#include <fiddle.h> - -void Init_fiddle_closure(void); - -#endif diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c deleted file mode 100644 index 298ed9775a..0000000000 --- a/ext/fiddle/conversions.c +++ /dev/null @@ -1,381 +0,0 @@ -#include <stdbool.h> - -#include <fiddle.h> - -VALUE -rb_fiddle_type_ensure(VALUE type) -{ - VALUE original_type = type; - - if (!RB_SYMBOL_P(type)) { - VALUE type_string = rb_check_string_type(type); - if (!NIL_P(type_string)) { - type = rb_to_symbol(type_string); - } - } - - if (RB_SYMBOL_P(type)) { - ID type_id = rb_sym2id(type); - ID void_id; - ID voidp_id; - ID char_id; - ID short_id; - ID int_id; - ID long_id; -#ifdef TYPE_LONG_LONG - ID long_long_id; -#endif -#ifdef TYPE_INT8_T - ID int8_t_id; -#endif -#ifdef TYPE_INT16_T - ID int16_t_id; -#endif -#ifdef TYPE_INT32_T - ID int32_t_id; -#endif -#ifdef TYPE_INT64_T - ID int64_t_id; -#endif - ID float_id; - ID double_id; - ID variadic_id; - ID const_string_id; - ID size_t_id; - ID ssize_t_id; - 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"); - RUBY_CONST_ID(short_id, "short"); - RUBY_CONST_ID(int_id, "int"); - RUBY_CONST_ID(long_id, "long"); -#ifdef TYPE_LONG_LONG - RUBY_CONST_ID(long_long_id, "long_long"); -#endif -#ifdef TYPE_INT8_T - RUBY_CONST_ID(int8_t_id, "int8_t"); -#endif -#ifdef TYPE_INT16_T - RUBY_CONST_ID(int16_t_id, "int16_t"); -#endif -#ifdef TYPE_INT32_T - RUBY_CONST_ID(int32_t_id, "int32_t"); -#endif -#ifdef TYPE_INT64_T - RUBY_CONST_ID(int64_t_id, "int64_t"); -#endif - RUBY_CONST_ID(float_id, "float"); - RUBY_CONST_ID(double_id, "double"); - RUBY_CONST_ID(variadic_id, "variadic"); - RUBY_CONST_ID(const_string_id, "const_string"); - RUBY_CONST_ID(size_t_id, "size_t"); - RUBY_CONST_ID(ssize_t_id, "ssize_t"); - 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); - } - else if (type_id == voidp_id) { - return INT2NUM(TYPE_VOIDP); - } - else if (type_id == char_id) { - return INT2NUM(TYPE_CHAR); - } - else if (type_id == short_id) { - return INT2NUM(TYPE_SHORT); - } - else if (type_id == int_id) { - return INT2NUM(TYPE_INT); - } - else if (type_id == long_id) { - return INT2NUM(TYPE_LONG); - } -#ifdef TYPE_LONG_LONG - else if (type_id == long_long_id) { - return INT2NUM(TYPE_LONG_LONG); - } -#endif -#ifdef TYPE_INT8_T - else if (type_id == int8_t_id) { - return INT2NUM(TYPE_INT8_T); - } -#endif -#ifdef TYPE_INT16_T - else if (type_id == int16_t_id) { - return INT2NUM(TYPE_INT16_T); - } -#endif -#ifdef TYPE_INT32_T - else if (type_id == int32_t_id) { - return INT2NUM(TYPE_INT32_T); - } -#endif -#ifdef TYPE_INT64_T - else if (type_id == int64_t_id) { - return INT2NUM(TYPE_INT64_T); - } -#endif - else if (type_id == float_id) { - return INT2NUM(TYPE_FLOAT); - } - else if (type_id == double_id) { - return INT2NUM(TYPE_DOUBLE); - } - else if (type_id == variadic_id) { - return INT2NUM(TYPE_VARIADIC); - } - else if (type_id == const_string_id) { - return INT2NUM(TYPE_CONST_STRING); - } - else if (type_id == size_t_id) { - return INT2NUM(TYPE_SIZE_T); - } - else if (type_id == ssize_t_id) { - return INT2NUM(TYPE_SSIZE_T); - } - else if (type_id == ptrdiff_t_id) { - return INT2NUM(TYPE_PTRDIFF_T); - } - else if (type_id == intptr_t_id) { - return INT2NUM(TYPE_INTPTR_T); - } - 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; - } - } - - return rb_to_int(type); -} - -ffi_type * -rb_fiddle_int_to_ffi_type(int type) -{ - int signed_p = 1; - - if (type < 0) { - type = -1 * type; - signed_p = 0; - } - -#define rb_ffi_type_of(t) (signed_p ? &ffi_type_s##t : &ffi_type_u##t) - - switch (type) { - case TYPE_VOID: - return &ffi_type_void; - case TYPE_VOIDP: - return &ffi_type_pointer; - case TYPE_CHAR: - return rb_ffi_type_of(char); - case TYPE_SHORT: - return rb_ffi_type_of(short); - case TYPE_INT: - return rb_ffi_type_of(int); - case TYPE_LONG: - return rb_ffi_type_of(long); -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - return rb_ffi_type_of(long_long); -#endif - case TYPE_FLOAT: - return &ffi_type_float; - case TYPE_DOUBLE: - 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); - } - return &ffi_type_pointer; -} - -ffi_type * -int_to_ffi_type(int type) -{ - return rb_fiddle_int_to_ffi_type(type); -} - -void -rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst) -{ - switch (type) { - case TYPE_VOID: - break; - case TYPE_VOIDP: - dst->pointer = NUM2PTR(rb_Integer(*src)); - break; - case TYPE_CHAR: - 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); - break; - case TYPE_SHORT: - dst->sshort = (unsigned short)NUM2INT(*src); - break; - case TYPE_USHORT: - dst->sshort = (signed short)NUM2UINT(*src); - break; - case TYPE_INT: - dst->sint = NUM2INT(*src); - break; - case TYPE_UINT: - dst->uint = NUM2UINT(*src); - break; - case TYPE_LONG: - dst->slong = NUM2LONG(*src); - break; - case TYPE_ULONG: - dst->ulong = NUM2ULONG(*src); - break; -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - dst->slong_long = NUM2LL(*src); - break; - case TYPE_ULONG_LONG: - dst->ulong_long = NUM2ULL(*src); - break; -#endif - case TYPE_FLOAT: - dst->ffloat = (float)NUM2DBL(*src); - break; - case TYPE_DOUBLE: - dst->ddouble = NUM2DBL(*src); - break; - case TYPE_CONST_STRING: - if (NIL_P(*src)) { - dst->pointer = NULL; - } - else { - 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; - } -} - -void -value_to_generic(int type, VALUE src, fiddle_generic *dst) -{ - /* src isn't safe from GC when type is TYPE_CONST_STRING and src - * isn't String. */ - rb_fiddle_value_to_generic(type, &src, dst); -} - -VALUE -rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval) -{ - int type = NUM2INT(rettype); - VALUE cPointer; - - cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - - switch (type) { - case TYPE_VOID: - return Qnil; - case TYPE_VOIDP: - return rb_funcall(cPointer, rb_intern("[]"), 1, - PTR2NUM((void *)retval.pointer)); - case TYPE_CHAR: - return INT2NUM((signed char)retval.fffi_sarg); - case TYPE_UCHAR: - return INT2NUM((unsigned char)retval.fffi_arg); - case TYPE_SHORT: - return INT2NUM((signed short)retval.fffi_sarg); - case TYPE_USHORT: - return INT2NUM((unsigned short)retval.fffi_arg); - case TYPE_INT: - return INT2NUM((signed int)retval.fffi_sarg); - case TYPE_UINT: - return UINT2NUM((unsigned int)retval.fffi_arg); - case TYPE_LONG: - return LONG2NUM(retval.slong); - case TYPE_ULONG: - return ULONG2NUM(retval.ulong); -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - return LL2NUM(retval.slong_long); - case TYPE_ULONG_LONG: - return ULL2NUM(retval.ulong_long); -#endif - case TYPE_FLOAT: - return rb_float_new(retval.ffloat); - case TYPE_DOUBLE: - return rb_float_new(retval.ddouble); - case TYPE_CONST_STRING: - if (retval.pointer) { - return rb_str_new_cstr(retval.pointer); - } - 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); - } - - UNREACHABLE; -} - -VALUE -generic_to_value(VALUE rettype, fiddle_generic retval) -{ - return rb_fiddle_generic_to_value(rettype, retval); -} diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h deleted file mode 100644 index 7a1e928d56..0000000000 --- a/ext/fiddle/conversions.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef FIDDLE_CONVERSIONS_H -#define FIDDLE_CONVERSIONS_H - -#include <fiddle.h> - -typedef union -{ - ffi_arg fffi_arg; /* rvalue smaller than unsigned long */ - ffi_sarg fffi_sarg; /* rvalue smaller than signed long */ - unsigned char uchar; /* ffi_type_uchar */ - signed char schar; /* ffi_type_schar */ - unsigned short ushort; /* ffi_type_sshort */ - signed short sshort; /* ffi_type_ushort */ - unsigned int uint; /* ffi_type_uint */ - signed int sint; /* ffi_type_sint */ - unsigned long ulong; /* ffi_type_ulong */ - signed long slong; /* ffi_type_slong */ - float ffloat; /* ffi_type_float */ - double ddouble; /* ffi_type_double */ -#if HAVE_LONG_LONG - unsigned LONG_LONG ulong_long; /* ffi_type_ulong_long */ - signed LONG_LONG slong_long; /* ffi_type_ulong_long */ -#endif - void * pointer; /* ffi_type_pointer */ -} fiddle_generic; - -VALUE rb_fiddle_type_ensure(VALUE type); -ffi_type * rb_fiddle_int_to_ffi_type(int type); -void rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst); -VALUE rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval); - -/* Deprecated. Use rb_fiddle_*() version. */ -ffi_type * int_to_ffi_type(int type); -void value_to_generic(int type, VALUE src, fiddle_generic *dst); -VALUE generic_to_value(VALUE rettype, fiddle_generic retval); - -#define VALUE2GENERIC(_type, _src, _dst) \ - rb_fiddle_value_to_generic((_type), &(_src), (_dst)) -#define INT2FFI_TYPE(_type) \ - rb_fiddle_int_to_ffi_type(_type) -#define GENERIC2VALUE(_type, _retval) \ - rb_fiddle_generic_to_value((_type), (_retval)) - -#if SIZEOF_VOIDP == SIZEOF_LONG -# define PTR2NUM(x) (LONG2NUM((long)(x))) -# define NUM2PTR(x) ((void*)(NUM2ULONG(x))) -#else -/* # error --->> Ruby/DL2 requires sizeof(void*) == sizeof(long) to be compiled. <<--- */ -# define PTR2NUM(x) (LL2NUM((LONG_LONG)(x))) -# 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 deleted file mode 100644 index 43b11ca780..0000000000 --- a/ext/fiddle/depend +++ /dev/null @@ -1,1396 +0,0 @@ -PWD = - -CONFIGURE_LIBFFI = \ - $(LIBFFI_CONFIGURE) --disable-shared \ - --host=$(LIBFFI_ARCH) --enable-builddir=$(arch) \ - CC="$(CC)" CFLAGS="$(LIBFFI_CFLAGS)" \ - LD="$(LD)" LDFLAGS="$(LIBFFI_LDFLAGS)" - -$(STATIC_LIB) $(RUBYARCHDIR)/$(DLLIB) $(DLLIB): $(LIBFFI_A) - -$(OBJS): $(FFI_H) - -.PHONY: .FORCE hdr - -.FORCE: - -hdr: $(FFI_H) - -configure-libffi build-libffi: .FORCE -configure-libffi \ -$(LIBFFI_DIR)/include/ffi.h \ -$(LIBFFI_DIR)/include/ffitarget.h \ -$(LIBFFI_DIR)/fficonfig.h \ -$(LIBFFI_DIR)/Makefile: - $(Q) $(MAKEDIRS) $(LIBFFI_DIR) - $(Q) $(CONFIGURE_LIBFFI) - -build-libffi $(LIBFFI_A): - $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) - -clean-none: -clean-libffi: - $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) clean - -distclean-none: -distclean-libffi: - $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) distclean - $(Q) $(RM) $(LIBFFI_DIR)/local.exp - $(Q) $(RUBY) -rfileutils -e "FileUtils.rmdir(Dir.glob(ARGV[0]+'/**/{,.*/}'), :parents=>true)" $(LIBFFI_DIR) - -realclean-none: -realclean-libffi: - $(Q) $(RMALL) $(LIBFFI_DIR) - -.PHONY: clean-libffi distclean-libffi realclean-libffi -.PHONY: clean-none distclean-none realclean-none - -clean: clean-$(LIBFFI_CLEAN) -distclean: distclean-$(LIBFFI_CLEAN) -realclean: realclean-$(LIBFFI_CLEAN) - -.PHONY: configure configure-libffi - -# AUTOGENERATED DEPENDENCIES START -closure.o: $(RUBY_EXTCONF_H) -closure.o: $(arch_hdrdir)/ruby/config.h -closure.o: $(hdrdir)/ruby.h -closure.o: $(hdrdir)/ruby/assert.h -closure.o: $(hdrdir)/ruby/backward.h -closure.o: $(hdrdir)/ruby/backward/2/assume.h -closure.o: $(hdrdir)/ruby/backward/2/attributes.h -closure.o: $(hdrdir)/ruby/backward/2/bool.h -closure.o: $(hdrdir)/ruby/backward/2/inttypes.h -closure.o: $(hdrdir)/ruby/backward/2/limits.h -closure.o: $(hdrdir)/ruby/backward/2/long_long.h -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 -closure.o: $(hdrdir)/ruby/internal/arithmetic/double.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/int.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/long.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/short.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -closure.o: $(hdrdir)/ruby/internal/assume.h -closure.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -closure.o: $(hdrdir)/ruby/internal/attr/artificial.h -closure.o: $(hdrdir)/ruby/internal/attr/cold.h -closure.o: $(hdrdir)/ruby/internal/attr/const.h -closure.o: $(hdrdir)/ruby/internal/attr/constexpr.h -closure.o: $(hdrdir)/ruby/internal/attr/deprecated.h -closure.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -closure.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -closure.o: $(hdrdir)/ruby/internal/attr/error.h -closure.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -closure.o: $(hdrdir)/ruby/internal/attr/forceinline.h -closure.o: $(hdrdir)/ruby/internal/attr/format.h -closure.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -closure.o: $(hdrdir)/ruby/internal/attr/noalias.h -closure.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -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 -closure.o: $(hdrdir)/ruby/internal/attr/warning.h -closure.o: $(hdrdir)/ruby/internal/attr/weakref.h -closure.o: $(hdrdir)/ruby/internal/cast.h -closure.o: $(hdrdir)/ruby/internal/compiler_is.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -closure.o: $(hdrdir)/ruby/internal/compiler_since.h -closure.o: $(hdrdir)/ruby/internal/config.h -closure.o: $(hdrdir)/ruby/internal/constant_p.h -closure.o: $(hdrdir)/ruby/internal/core.h -closure.o: $(hdrdir)/ruby/internal/core/rarray.h -closure.o: $(hdrdir)/ruby/internal/core/rbasic.h -closure.o: $(hdrdir)/ruby/internal/core/rbignum.h -closure.o: $(hdrdir)/ruby/internal/core/rclass.h -closure.o: $(hdrdir)/ruby/internal/core/rdata.h -closure.o: $(hdrdir)/ruby/internal/core/rfile.h -closure.o: $(hdrdir)/ruby/internal/core/rhash.h -closure.o: $(hdrdir)/ruby/internal/core/robject.h -closure.o: $(hdrdir)/ruby/internal/core/rregexp.h -closure.o: $(hdrdir)/ruby/internal/core/rstring.h -closure.o: $(hdrdir)/ruby/internal/core/rstruct.h -closure.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -closure.o: $(hdrdir)/ruby/internal/ctype.h -closure.o: $(hdrdir)/ruby/internal/dllexport.h -closure.o: $(hdrdir)/ruby/internal/dosish.h -closure.o: $(hdrdir)/ruby/internal/error.h -closure.o: $(hdrdir)/ruby/internal/eval.h -closure.o: $(hdrdir)/ruby/internal/event.h -closure.o: $(hdrdir)/ruby/internal/fl_type.h -closure.o: $(hdrdir)/ruby/internal/gc.h -closure.o: $(hdrdir)/ruby/internal/glob.h -closure.o: $(hdrdir)/ruby/internal/globals.h -closure.o: $(hdrdir)/ruby/internal/has/attribute.h -closure.o: $(hdrdir)/ruby/internal/has/builtin.h -closure.o: $(hdrdir)/ruby/internal/has/c_attribute.h -closure.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -closure.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -closure.o: $(hdrdir)/ruby/internal/has/extension.h -closure.o: $(hdrdir)/ruby/internal/has/feature.h -closure.o: $(hdrdir)/ruby/internal/has/warning.h -closure.o: $(hdrdir)/ruby/internal/intern/array.h -closure.o: $(hdrdir)/ruby/internal/intern/bignum.h -closure.o: $(hdrdir)/ruby/internal/intern/class.h -closure.o: $(hdrdir)/ruby/internal/intern/compar.h -closure.o: $(hdrdir)/ruby/internal/intern/complex.h -closure.o: $(hdrdir)/ruby/internal/intern/cont.h -closure.o: $(hdrdir)/ruby/internal/intern/dir.h -closure.o: $(hdrdir)/ruby/internal/intern/enum.h -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/hash.h -closure.o: $(hdrdir)/ruby/internal/intern/io.h -closure.o: $(hdrdir)/ruby/internal/intern/load.h -closure.o: $(hdrdir)/ruby/internal/intern/marshal.h -closure.o: $(hdrdir)/ruby/internal/intern/numeric.h -closure.o: $(hdrdir)/ruby/internal/intern/object.h -closure.o: $(hdrdir)/ruby/internal/intern/parse.h -closure.o: $(hdrdir)/ruby/internal/intern/proc.h -closure.o: $(hdrdir)/ruby/internal/intern/process.h -closure.o: $(hdrdir)/ruby/internal/intern/random.h -closure.o: $(hdrdir)/ruby/internal/intern/range.h -closure.o: $(hdrdir)/ruby/internal/intern/rational.h -closure.o: $(hdrdir)/ruby/internal/intern/re.h -closure.o: $(hdrdir)/ruby/internal/intern/ruby.h -closure.o: $(hdrdir)/ruby/internal/intern/select.h -closure.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -closure.o: $(hdrdir)/ruby/internal/intern/signal.h -closure.o: $(hdrdir)/ruby/internal/intern/sprintf.h -closure.o: $(hdrdir)/ruby/internal/intern/string.h -closure.o: $(hdrdir)/ruby/internal/intern/struct.h -closure.o: $(hdrdir)/ruby/internal/intern/thread.h -closure.o: $(hdrdir)/ruby/internal/intern/time.h -closure.o: $(hdrdir)/ruby/internal/intern/variable.h -closure.o: $(hdrdir)/ruby/internal/intern/vm.h -closure.o: $(hdrdir)/ruby/internal/interpreter.h -closure.o: $(hdrdir)/ruby/internal/iterator.h -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/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 -closure.o: $(hdrdir)/ruby/internal/variable.h -closure.o: $(hdrdir)/ruby/internal/warning_push.h -closure.o: $(hdrdir)/ruby/internal/xmalloc.h -closure.o: $(hdrdir)/ruby/missing.h -closure.o: $(hdrdir)/ruby/ruby.h -closure.o: $(hdrdir)/ruby/st.h -closure.o: $(hdrdir)/ruby/subst.h -closure.o: $(hdrdir)/ruby/thread.h -closure.o: closure.c -closure.o: closure.h -closure.o: conversions.h -closure.o: fiddle.h -closure.o: function.h -conversions.o: $(RUBY_EXTCONF_H) -conversions.o: $(arch_hdrdir)/ruby/config.h -conversions.o: $(hdrdir)/ruby.h -conversions.o: $(hdrdir)/ruby/assert.h -conversions.o: $(hdrdir)/ruby/backward.h -conversions.o: $(hdrdir)/ruby/backward/2/assume.h -conversions.o: $(hdrdir)/ruby/backward/2/attributes.h -conversions.o: $(hdrdir)/ruby/backward/2/bool.h -conversions.o: $(hdrdir)/ruby/backward/2/inttypes.h -conversions.o: $(hdrdir)/ruby/backward/2/limits.h -conversions.o: $(hdrdir)/ruby/backward/2/long_long.h -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 -conversions.o: $(hdrdir)/ruby/internal/arithmetic/double.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/int.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/long.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/short.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -conversions.o: $(hdrdir)/ruby/internal/assume.h -conversions.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -conversions.o: $(hdrdir)/ruby/internal/attr/artificial.h -conversions.o: $(hdrdir)/ruby/internal/attr/cold.h -conversions.o: $(hdrdir)/ruby/internal/attr/const.h -conversions.o: $(hdrdir)/ruby/internal/attr/constexpr.h -conversions.o: $(hdrdir)/ruby/internal/attr/deprecated.h -conversions.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -conversions.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -conversions.o: $(hdrdir)/ruby/internal/attr/error.h -conversions.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -conversions.o: $(hdrdir)/ruby/internal/attr/forceinline.h -conversions.o: $(hdrdir)/ruby/internal/attr/format.h -conversions.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -conversions.o: $(hdrdir)/ruby/internal/attr/noalias.h -conversions.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -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 -conversions.o: $(hdrdir)/ruby/internal/attr/warning.h -conversions.o: $(hdrdir)/ruby/internal/attr/weakref.h -conversions.o: $(hdrdir)/ruby/internal/cast.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -conversions.o: $(hdrdir)/ruby/internal/compiler_since.h -conversions.o: $(hdrdir)/ruby/internal/config.h -conversions.o: $(hdrdir)/ruby/internal/constant_p.h -conversions.o: $(hdrdir)/ruby/internal/core.h -conversions.o: $(hdrdir)/ruby/internal/core/rarray.h -conversions.o: $(hdrdir)/ruby/internal/core/rbasic.h -conversions.o: $(hdrdir)/ruby/internal/core/rbignum.h -conversions.o: $(hdrdir)/ruby/internal/core/rclass.h -conversions.o: $(hdrdir)/ruby/internal/core/rdata.h -conversions.o: $(hdrdir)/ruby/internal/core/rfile.h -conversions.o: $(hdrdir)/ruby/internal/core/rhash.h -conversions.o: $(hdrdir)/ruby/internal/core/robject.h -conversions.o: $(hdrdir)/ruby/internal/core/rregexp.h -conversions.o: $(hdrdir)/ruby/internal/core/rstring.h -conversions.o: $(hdrdir)/ruby/internal/core/rstruct.h -conversions.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -conversions.o: $(hdrdir)/ruby/internal/ctype.h -conversions.o: $(hdrdir)/ruby/internal/dllexport.h -conversions.o: $(hdrdir)/ruby/internal/dosish.h -conversions.o: $(hdrdir)/ruby/internal/error.h -conversions.o: $(hdrdir)/ruby/internal/eval.h -conversions.o: $(hdrdir)/ruby/internal/event.h -conversions.o: $(hdrdir)/ruby/internal/fl_type.h -conversions.o: $(hdrdir)/ruby/internal/gc.h -conversions.o: $(hdrdir)/ruby/internal/glob.h -conversions.o: $(hdrdir)/ruby/internal/globals.h -conversions.o: $(hdrdir)/ruby/internal/has/attribute.h -conversions.o: $(hdrdir)/ruby/internal/has/builtin.h -conversions.o: $(hdrdir)/ruby/internal/has/c_attribute.h -conversions.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -conversions.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -conversions.o: $(hdrdir)/ruby/internal/has/extension.h -conversions.o: $(hdrdir)/ruby/internal/has/feature.h -conversions.o: $(hdrdir)/ruby/internal/has/warning.h -conversions.o: $(hdrdir)/ruby/internal/intern/array.h -conversions.o: $(hdrdir)/ruby/internal/intern/bignum.h -conversions.o: $(hdrdir)/ruby/internal/intern/class.h -conversions.o: $(hdrdir)/ruby/internal/intern/compar.h -conversions.o: $(hdrdir)/ruby/internal/intern/complex.h -conversions.o: $(hdrdir)/ruby/internal/intern/cont.h -conversions.o: $(hdrdir)/ruby/internal/intern/dir.h -conversions.o: $(hdrdir)/ruby/internal/intern/enum.h -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/hash.h -conversions.o: $(hdrdir)/ruby/internal/intern/io.h -conversions.o: $(hdrdir)/ruby/internal/intern/load.h -conversions.o: $(hdrdir)/ruby/internal/intern/marshal.h -conversions.o: $(hdrdir)/ruby/internal/intern/numeric.h -conversions.o: $(hdrdir)/ruby/internal/intern/object.h -conversions.o: $(hdrdir)/ruby/internal/intern/parse.h -conversions.o: $(hdrdir)/ruby/internal/intern/proc.h -conversions.o: $(hdrdir)/ruby/internal/intern/process.h -conversions.o: $(hdrdir)/ruby/internal/intern/random.h -conversions.o: $(hdrdir)/ruby/internal/intern/range.h -conversions.o: $(hdrdir)/ruby/internal/intern/rational.h -conversions.o: $(hdrdir)/ruby/internal/intern/re.h -conversions.o: $(hdrdir)/ruby/internal/intern/ruby.h -conversions.o: $(hdrdir)/ruby/internal/intern/select.h -conversions.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -conversions.o: $(hdrdir)/ruby/internal/intern/signal.h -conversions.o: $(hdrdir)/ruby/internal/intern/sprintf.h -conversions.o: $(hdrdir)/ruby/internal/intern/string.h -conversions.o: $(hdrdir)/ruby/internal/intern/struct.h -conversions.o: $(hdrdir)/ruby/internal/intern/thread.h -conversions.o: $(hdrdir)/ruby/internal/intern/time.h -conversions.o: $(hdrdir)/ruby/internal/intern/variable.h -conversions.o: $(hdrdir)/ruby/internal/intern/vm.h -conversions.o: $(hdrdir)/ruby/internal/interpreter.h -conversions.o: $(hdrdir)/ruby/internal/iterator.h -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/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 -conversions.o: $(hdrdir)/ruby/internal/variable.h -conversions.o: $(hdrdir)/ruby/internal/warning_push.h -conversions.o: $(hdrdir)/ruby/internal/xmalloc.h -conversions.o: $(hdrdir)/ruby/missing.h -conversions.o: $(hdrdir)/ruby/ruby.h -conversions.o: $(hdrdir)/ruby/st.h -conversions.o: $(hdrdir)/ruby/subst.h -conversions.o: closure.h -conversions.o: conversions.c -conversions.o: conversions.h -conversions.o: fiddle.h -conversions.o: function.h -fiddle.o: $(RUBY_EXTCONF_H) -fiddle.o: $(arch_hdrdir)/ruby/config.h -fiddle.o: $(hdrdir)/ruby.h -fiddle.o: $(hdrdir)/ruby/assert.h -fiddle.o: $(hdrdir)/ruby/backward.h -fiddle.o: $(hdrdir)/ruby/backward/2/assume.h -fiddle.o: $(hdrdir)/ruby/backward/2/attributes.h -fiddle.o: $(hdrdir)/ruby/backward/2/bool.h -fiddle.o: $(hdrdir)/ruby/backward/2/inttypes.h -fiddle.o: $(hdrdir)/ruby/backward/2/limits.h -fiddle.o: $(hdrdir)/ruby/backward/2/long_long.h -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 -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/double.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/int.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/long.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/short.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -fiddle.o: $(hdrdir)/ruby/internal/assume.h -fiddle.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -fiddle.o: $(hdrdir)/ruby/internal/attr/artificial.h -fiddle.o: $(hdrdir)/ruby/internal/attr/cold.h -fiddle.o: $(hdrdir)/ruby/internal/attr/const.h -fiddle.o: $(hdrdir)/ruby/internal/attr/constexpr.h -fiddle.o: $(hdrdir)/ruby/internal/attr/deprecated.h -fiddle.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -fiddle.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -fiddle.o: $(hdrdir)/ruby/internal/attr/error.h -fiddle.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -fiddle.o: $(hdrdir)/ruby/internal/attr/forceinline.h -fiddle.o: $(hdrdir)/ruby/internal/attr/format.h -fiddle.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -fiddle.o: $(hdrdir)/ruby/internal/attr/noalias.h -fiddle.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -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 -fiddle.o: $(hdrdir)/ruby/internal/attr/warning.h -fiddle.o: $(hdrdir)/ruby/internal/attr/weakref.h -fiddle.o: $(hdrdir)/ruby/internal/cast.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_since.h -fiddle.o: $(hdrdir)/ruby/internal/config.h -fiddle.o: $(hdrdir)/ruby/internal/constant_p.h -fiddle.o: $(hdrdir)/ruby/internal/core.h -fiddle.o: $(hdrdir)/ruby/internal/core/rarray.h -fiddle.o: $(hdrdir)/ruby/internal/core/rbasic.h -fiddle.o: $(hdrdir)/ruby/internal/core/rbignum.h -fiddle.o: $(hdrdir)/ruby/internal/core/rclass.h -fiddle.o: $(hdrdir)/ruby/internal/core/rdata.h -fiddle.o: $(hdrdir)/ruby/internal/core/rfile.h -fiddle.o: $(hdrdir)/ruby/internal/core/rhash.h -fiddle.o: $(hdrdir)/ruby/internal/core/robject.h -fiddle.o: $(hdrdir)/ruby/internal/core/rregexp.h -fiddle.o: $(hdrdir)/ruby/internal/core/rstring.h -fiddle.o: $(hdrdir)/ruby/internal/core/rstruct.h -fiddle.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -fiddle.o: $(hdrdir)/ruby/internal/ctype.h -fiddle.o: $(hdrdir)/ruby/internal/dllexport.h -fiddle.o: $(hdrdir)/ruby/internal/dosish.h -fiddle.o: $(hdrdir)/ruby/internal/error.h -fiddle.o: $(hdrdir)/ruby/internal/eval.h -fiddle.o: $(hdrdir)/ruby/internal/event.h -fiddle.o: $(hdrdir)/ruby/internal/fl_type.h -fiddle.o: $(hdrdir)/ruby/internal/gc.h -fiddle.o: $(hdrdir)/ruby/internal/glob.h -fiddle.o: $(hdrdir)/ruby/internal/globals.h -fiddle.o: $(hdrdir)/ruby/internal/has/attribute.h -fiddle.o: $(hdrdir)/ruby/internal/has/builtin.h -fiddle.o: $(hdrdir)/ruby/internal/has/c_attribute.h -fiddle.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -fiddle.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -fiddle.o: $(hdrdir)/ruby/internal/has/extension.h -fiddle.o: $(hdrdir)/ruby/internal/has/feature.h -fiddle.o: $(hdrdir)/ruby/internal/has/warning.h -fiddle.o: $(hdrdir)/ruby/internal/intern/array.h -fiddle.o: $(hdrdir)/ruby/internal/intern/bignum.h -fiddle.o: $(hdrdir)/ruby/internal/intern/class.h -fiddle.o: $(hdrdir)/ruby/internal/intern/compar.h -fiddle.o: $(hdrdir)/ruby/internal/intern/complex.h -fiddle.o: $(hdrdir)/ruby/internal/intern/cont.h -fiddle.o: $(hdrdir)/ruby/internal/intern/dir.h -fiddle.o: $(hdrdir)/ruby/internal/intern/enum.h -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/hash.h -fiddle.o: $(hdrdir)/ruby/internal/intern/io.h -fiddle.o: $(hdrdir)/ruby/internal/intern/load.h -fiddle.o: $(hdrdir)/ruby/internal/intern/marshal.h -fiddle.o: $(hdrdir)/ruby/internal/intern/numeric.h -fiddle.o: $(hdrdir)/ruby/internal/intern/object.h -fiddle.o: $(hdrdir)/ruby/internal/intern/parse.h -fiddle.o: $(hdrdir)/ruby/internal/intern/proc.h -fiddle.o: $(hdrdir)/ruby/internal/intern/process.h -fiddle.o: $(hdrdir)/ruby/internal/intern/random.h -fiddle.o: $(hdrdir)/ruby/internal/intern/range.h -fiddle.o: $(hdrdir)/ruby/internal/intern/rational.h -fiddle.o: $(hdrdir)/ruby/internal/intern/re.h -fiddle.o: $(hdrdir)/ruby/internal/intern/ruby.h -fiddle.o: $(hdrdir)/ruby/internal/intern/select.h -fiddle.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -fiddle.o: $(hdrdir)/ruby/internal/intern/signal.h -fiddle.o: $(hdrdir)/ruby/internal/intern/sprintf.h -fiddle.o: $(hdrdir)/ruby/internal/intern/string.h -fiddle.o: $(hdrdir)/ruby/internal/intern/struct.h -fiddle.o: $(hdrdir)/ruby/internal/intern/thread.h -fiddle.o: $(hdrdir)/ruby/internal/intern/time.h -fiddle.o: $(hdrdir)/ruby/internal/intern/variable.h -fiddle.o: $(hdrdir)/ruby/internal/intern/vm.h -fiddle.o: $(hdrdir)/ruby/internal/interpreter.h -fiddle.o: $(hdrdir)/ruby/internal/iterator.h -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/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 -fiddle.o: $(hdrdir)/ruby/internal/variable.h -fiddle.o: $(hdrdir)/ruby/internal/warning_push.h -fiddle.o: $(hdrdir)/ruby/internal/xmalloc.h -fiddle.o: $(hdrdir)/ruby/missing.h -fiddle.o: $(hdrdir)/ruby/ruby.h -fiddle.o: $(hdrdir)/ruby/st.h -fiddle.o: $(hdrdir)/ruby/subst.h -fiddle.o: closure.h -fiddle.o: conversions.h -fiddle.o: fiddle.c -fiddle.o: fiddle.h -fiddle.o: function.h -function.o: $(RUBY_EXTCONF_H) -function.o: $(arch_hdrdir)/ruby/config.h -function.o: $(hdrdir)/ruby.h -function.o: $(hdrdir)/ruby/assert.h -function.o: $(hdrdir)/ruby/backward.h -function.o: $(hdrdir)/ruby/backward/2/assume.h -function.o: $(hdrdir)/ruby/backward/2/attributes.h -function.o: $(hdrdir)/ruby/backward/2/bool.h -function.o: $(hdrdir)/ruby/backward/2/inttypes.h -function.o: $(hdrdir)/ruby/backward/2/limits.h -function.o: $(hdrdir)/ruby/backward/2/long_long.h -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 -function.o: $(hdrdir)/ruby/internal/arithmetic/double.h -function.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -function.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/int.h -function.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/long.h -function.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -function.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/short.h -function.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -function.o: $(hdrdir)/ruby/internal/assume.h -function.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -function.o: $(hdrdir)/ruby/internal/attr/artificial.h -function.o: $(hdrdir)/ruby/internal/attr/cold.h -function.o: $(hdrdir)/ruby/internal/attr/const.h -function.o: $(hdrdir)/ruby/internal/attr/constexpr.h -function.o: $(hdrdir)/ruby/internal/attr/deprecated.h -function.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -function.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -function.o: $(hdrdir)/ruby/internal/attr/error.h -function.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -function.o: $(hdrdir)/ruby/internal/attr/forceinline.h -function.o: $(hdrdir)/ruby/internal/attr/format.h -function.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -function.o: $(hdrdir)/ruby/internal/attr/noalias.h -function.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -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 -function.o: $(hdrdir)/ruby/internal/attr/warning.h -function.o: $(hdrdir)/ruby/internal/attr/weakref.h -function.o: $(hdrdir)/ruby/internal/cast.h -function.o: $(hdrdir)/ruby/internal/compiler_is.h -function.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -function.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -function.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -function.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -function.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -function.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -function.o: $(hdrdir)/ruby/internal/compiler_since.h -function.o: $(hdrdir)/ruby/internal/config.h -function.o: $(hdrdir)/ruby/internal/constant_p.h -function.o: $(hdrdir)/ruby/internal/core.h -function.o: $(hdrdir)/ruby/internal/core/rarray.h -function.o: $(hdrdir)/ruby/internal/core/rbasic.h -function.o: $(hdrdir)/ruby/internal/core/rbignum.h -function.o: $(hdrdir)/ruby/internal/core/rclass.h -function.o: $(hdrdir)/ruby/internal/core/rdata.h -function.o: $(hdrdir)/ruby/internal/core/rfile.h -function.o: $(hdrdir)/ruby/internal/core/rhash.h -function.o: $(hdrdir)/ruby/internal/core/robject.h -function.o: $(hdrdir)/ruby/internal/core/rregexp.h -function.o: $(hdrdir)/ruby/internal/core/rstring.h -function.o: $(hdrdir)/ruby/internal/core/rstruct.h -function.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -function.o: $(hdrdir)/ruby/internal/ctype.h -function.o: $(hdrdir)/ruby/internal/dllexport.h -function.o: $(hdrdir)/ruby/internal/dosish.h -function.o: $(hdrdir)/ruby/internal/error.h -function.o: $(hdrdir)/ruby/internal/eval.h -function.o: $(hdrdir)/ruby/internal/event.h -function.o: $(hdrdir)/ruby/internal/fl_type.h -function.o: $(hdrdir)/ruby/internal/gc.h -function.o: $(hdrdir)/ruby/internal/glob.h -function.o: $(hdrdir)/ruby/internal/globals.h -function.o: $(hdrdir)/ruby/internal/has/attribute.h -function.o: $(hdrdir)/ruby/internal/has/builtin.h -function.o: $(hdrdir)/ruby/internal/has/c_attribute.h -function.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -function.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -function.o: $(hdrdir)/ruby/internal/has/extension.h -function.o: $(hdrdir)/ruby/internal/has/feature.h -function.o: $(hdrdir)/ruby/internal/has/warning.h -function.o: $(hdrdir)/ruby/internal/intern/array.h -function.o: $(hdrdir)/ruby/internal/intern/bignum.h -function.o: $(hdrdir)/ruby/internal/intern/class.h -function.o: $(hdrdir)/ruby/internal/intern/compar.h -function.o: $(hdrdir)/ruby/internal/intern/complex.h -function.o: $(hdrdir)/ruby/internal/intern/cont.h -function.o: $(hdrdir)/ruby/internal/intern/dir.h -function.o: $(hdrdir)/ruby/internal/intern/enum.h -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/hash.h -function.o: $(hdrdir)/ruby/internal/intern/io.h -function.o: $(hdrdir)/ruby/internal/intern/load.h -function.o: $(hdrdir)/ruby/internal/intern/marshal.h -function.o: $(hdrdir)/ruby/internal/intern/numeric.h -function.o: $(hdrdir)/ruby/internal/intern/object.h -function.o: $(hdrdir)/ruby/internal/intern/parse.h -function.o: $(hdrdir)/ruby/internal/intern/proc.h -function.o: $(hdrdir)/ruby/internal/intern/process.h -function.o: $(hdrdir)/ruby/internal/intern/random.h -function.o: $(hdrdir)/ruby/internal/intern/range.h -function.o: $(hdrdir)/ruby/internal/intern/rational.h -function.o: $(hdrdir)/ruby/internal/intern/re.h -function.o: $(hdrdir)/ruby/internal/intern/ruby.h -function.o: $(hdrdir)/ruby/internal/intern/select.h -function.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -function.o: $(hdrdir)/ruby/internal/intern/signal.h -function.o: $(hdrdir)/ruby/internal/intern/sprintf.h -function.o: $(hdrdir)/ruby/internal/intern/string.h -function.o: $(hdrdir)/ruby/internal/intern/struct.h -function.o: $(hdrdir)/ruby/internal/intern/thread.h -function.o: $(hdrdir)/ruby/internal/intern/time.h -function.o: $(hdrdir)/ruby/internal/intern/variable.h -function.o: $(hdrdir)/ruby/internal/intern/vm.h -function.o: $(hdrdir)/ruby/internal/interpreter.h -function.o: $(hdrdir)/ruby/internal/iterator.h -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/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 -function.o: $(hdrdir)/ruby/internal/variable.h -function.o: $(hdrdir)/ruby/internal/warning_push.h -function.o: $(hdrdir)/ruby/internal/xmalloc.h -function.o: $(hdrdir)/ruby/missing.h -function.o: $(hdrdir)/ruby/ruby.h -function.o: $(hdrdir)/ruby/st.h -function.o: $(hdrdir)/ruby/subst.h -function.o: $(hdrdir)/ruby/thread.h -function.o: closure.h -function.o: conversions.h -function.o: fiddle.h -function.o: function.c -function.o: function.h -handle.o: $(RUBY_EXTCONF_H) -handle.o: $(arch_hdrdir)/ruby/config.h -handle.o: $(hdrdir)/ruby.h -handle.o: $(hdrdir)/ruby/assert.h -handle.o: $(hdrdir)/ruby/backward.h -handle.o: $(hdrdir)/ruby/backward/2/assume.h -handle.o: $(hdrdir)/ruby/backward/2/attributes.h -handle.o: $(hdrdir)/ruby/backward/2/bool.h -handle.o: $(hdrdir)/ruby/backward/2/inttypes.h -handle.o: $(hdrdir)/ruby/backward/2/limits.h -handle.o: $(hdrdir)/ruby/backward/2/long_long.h -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 -handle.o: $(hdrdir)/ruby/internal/arithmetic/double.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/int.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/long.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/short.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -handle.o: $(hdrdir)/ruby/internal/assume.h -handle.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -handle.o: $(hdrdir)/ruby/internal/attr/artificial.h -handle.o: $(hdrdir)/ruby/internal/attr/cold.h -handle.o: $(hdrdir)/ruby/internal/attr/const.h -handle.o: $(hdrdir)/ruby/internal/attr/constexpr.h -handle.o: $(hdrdir)/ruby/internal/attr/deprecated.h -handle.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -handle.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -handle.o: $(hdrdir)/ruby/internal/attr/error.h -handle.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -handle.o: $(hdrdir)/ruby/internal/attr/forceinline.h -handle.o: $(hdrdir)/ruby/internal/attr/format.h -handle.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -handle.o: $(hdrdir)/ruby/internal/attr/noalias.h -handle.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -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 -handle.o: $(hdrdir)/ruby/internal/attr/warning.h -handle.o: $(hdrdir)/ruby/internal/attr/weakref.h -handle.o: $(hdrdir)/ruby/internal/cast.h -handle.o: $(hdrdir)/ruby/internal/compiler_is.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -handle.o: $(hdrdir)/ruby/internal/compiler_since.h -handle.o: $(hdrdir)/ruby/internal/config.h -handle.o: $(hdrdir)/ruby/internal/constant_p.h -handle.o: $(hdrdir)/ruby/internal/core.h -handle.o: $(hdrdir)/ruby/internal/core/rarray.h -handle.o: $(hdrdir)/ruby/internal/core/rbasic.h -handle.o: $(hdrdir)/ruby/internal/core/rbignum.h -handle.o: $(hdrdir)/ruby/internal/core/rclass.h -handle.o: $(hdrdir)/ruby/internal/core/rdata.h -handle.o: $(hdrdir)/ruby/internal/core/rfile.h -handle.o: $(hdrdir)/ruby/internal/core/rhash.h -handle.o: $(hdrdir)/ruby/internal/core/robject.h -handle.o: $(hdrdir)/ruby/internal/core/rregexp.h -handle.o: $(hdrdir)/ruby/internal/core/rstring.h -handle.o: $(hdrdir)/ruby/internal/core/rstruct.h -handle.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -handle.o: $(hdrdir)/ruby/internal/ctype.h -handle.o: $(hdrdir)/ruby/internal/dllexport.h -handle.o: $(hdrdir)/ruby/internal/dosish.h -handle.o: $(hdrdir)/ruby/internal/error.h -handle.o: $(hdrdir)/ruby/internal/eval.h -handle.o: $(hdrdir)/ruby/internal/event.h -handle.o: $(hdrdir)/ruby/internal/fl_type.h -handle.o: $(hdrdir)/ruby/internal/gc.h -handle.o: $(hdrdir)/ruby/internal/glob.h -handle.o: $(hdrdir)/ruby/internal/globals.h -handle.o: $(hdrdir)/ruby/internal/has/attribute.h -handle.o: $(hdrdir)/ruby/internal/has/builtin.h -handle.o: $(hdrdir)/ruby/internal/has/c_attribute.h -handle.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -handle.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -handle.o: $(hdrdir)/ruby/internal/has/extension.h -handle.o: $(hdrdir)/ruby/internal/has/feature.h -handle.o: $(hdrdir)/ruby/internal/has/warning.h -handle.o: $(hdrdir)/ruby/internal/intern/array.h -handle.o: $(hdrdir)/ruby/internal/intern/bignum.h -handle.o: $(hdrdir)/ruby/internal/intern/class.h -handle.o: $(hdrdir)/ruby/internal/intern/compar.h -handle.o: $(hdrdir)/ruby/internal/intern/complex.h -handle.o: $(hdrdir)/ruby/internal/intern/cont.h -handle.o: $(hdrdir)/ruby/internal/intern/dir.h -handle.o: $(hdrdir)/ruby/internal/intern/enum.h -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/hash.h -handle.o: $(hdrdir)/ruby/internal/intern/io.h -handle.o: $(hdrdir)/ruby/internal/intern/load.h -handle.o: $(hdrdir)/ruby/internal/intern/marshal.h -handle.o: $(hdrdir)/ruby/internal/intern/numeric.h -handle.o: $(hdrdir)/ruby/internal/intern/object.h -handle.o: $(hdrdir)/ruby/internal/intern/parse.h -handle.o: $(hdrdir)/ruby/internal/intern/proc.h -handle.o: $(hdrdir)/ruby/internal/intern/process.h -handle.o: $(hdrdir)/ruby/internal/intern/random.h -handle.o: $(hdrdir)/ruby/internal/intern/range.h -handle.o: $(hdrdir)/ruby/internal/intern/rational.h -handle.o: $(hdrdir)/ruby/internal/intern/re.h -handle.o: $(hdrdir)/ruby/internal/intern/ruby.h -handle.o: $(hdrdir)/ruby/internal/intern/select.h -handle.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -handle.o: $(hdrdir)/ruby/internal/intern/signal.h -handle.o: $(hdrdir)/ruby/internal/intern/sprintf.h -handle.o: $(hdrdir)/ruby/internal/intern/string.h -handle.o: $(hdrdir)/ruby/internal/intern/struct.h -handle.o: $(hdrdir)/ruby/internal/intern/thread.h -handle.o: $(hdrdir)/ruby/internal/intern/time.h -handle.o: $(hdrdir)/ruby/internal/intern/variable.h -handle.o: $(hdrdir)/ruby/internal/intern/vm.h -handle.o: $(hdrdir)/ruby/internal/interpreter.h -handle.o: $(hdrdir)/ruby/internal/iterator.h -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/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 -handle.o: $(hdrdir)/ruby/internal/variable.h -handle.o: $(hdrdir)/ruby/internal/warning_push.h -handle.o: $(hdrdir)/ruby/internal/xmalloc.h -handle.o: $(hdrdir)/ruby/missing.h -handle.o: $(hdrdir)/ruby/ruby.h -handle.o: $(hdrdir)/ruby/st.h -handle.o: $(hdrdir)/ruby/subst.h -handle.o: closure.h -handle.o: conversions.h -handle.o: fiddle.h -handle.o: function.h -handle.o: handle.c -memory_view.o: $(RUBY_EXTCONF_H) -memory_view.o: $(arch_hdrdir)/ruby/config.h -memory_view.o: $(hdrdir)/ruby.h -memory_view.o: $(hdrdir)/ruby/assert.h -memory_view.o: $(hdrdir)/ruby/backward.h -memory_view.o: $(hdrdir)/ruby/backward/2/assume.h -memory_view.o: $(hdrdir)/ruby/backward/2/attributes.h -memory_view.o: $(hdrdir)/ruby/backward/2/bool.h -memory_view.o: $(hdrdir)/ruby/backward/2/inttypes.h -memory_view.o: $(hdrdir)/ruby/backward/2/limits.h -memory_view.o: $(hdrdir)/ruby/backward/2/long_long.h -memory_view.o: $(hdrdir)/ruby/backward/2/stdalign.h -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 -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/double.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/int.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/short.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -memory_view.o: $(hdrdir)/ruby/internal/assume.h -memory_view.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -memory_view.o: $(hdrdir)/ruby/internal/attr/artificial.h -memory_view.o: $(hdrdir)/ruby/internal/attr/cold.h -memory_view.o: $(hdrdir)/ruby/internal/attr/const.h -memory_view.o: $(hdrdir)/ruby/internal/attr/constexpr.h -memory_view.o: $(hdrdir)/ruby/internal/attr/deprecated.h -memory_view.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -memory_view.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -memory_view.o: $(hdrdir)/ruby/internal/attr/error.h -memory_view.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -memory_view.o: $(hdrdir)/ruby/internal/attr/forceinline.h -memory_view.o: $(hdrdir)/ruby/internal/attr/format.h -memory_view.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -memory_view.o: $(hdrdir)/ruby/internal/attr/noalias.h -memory_view.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -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 -memory_view.o: $(hdrdir)/ruby/internal/attr/warning.h -memory_view.o: $(hdrdir)/ruby/internal/attr/weakref.h -memory_view.o: $(hdrdir)/ruby/internal/cast.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_since.h -memory_view.o: $(hdrdir)/ruby/internal/config.h -memory_view.o: $(hdrdir)/ruby/internal/constant_p.h -memory_view.o: $(hdrdir)/ruby/internal/core.h -memory_view.o: $(hdrdir)/ruby/internal/core/rarray.h -memory_view.o: $(hdrdir)/ruby/internal/core/rbasic.h -memory_view.o: $(hdrdir)/ruby/internal/core/rbignum.h -memory_view.o: $(hdrdir)/ruby/internal/core/rclass.h -memory_view.o: $(hdrdir)/ruby/internal/core/rdata.h -memory_view.o: $(hdrdir)/ruby/internal/core/rfile.h -memory_view.o: $(hdrdir)/ruby/internal/core/rhash.h -memory_view.o: $(hdrdir)/ruby/internal/core/robject.h -memory_view.o: $(hdrdir)/ruby/internal/core/rregexp.h -memory_view.o: $(hdrdir)/ruby/internal/core/rstring.h -memory_view.o: $(hdrdir)/ruby/internal/core/rstruct.h -memory_view.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -memory_view.o: $(hdrdir)/ruby/internal/ctype.h -memory_view.o: $(hdrdir)/ruby/internal/dllexport.h -memory_view.o: $(hdrdir)/ruby/internal/dosish.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/coderange.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/ctype.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/encoding.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/pathname.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/re.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/sprintf.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/string.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/symbol.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/transcode.h -memory_view.o: $(hdrdir)/ruby/internal/error.h -memory_view.o: $(hdrdir)/ruby/internal/eval.h -memory_view.o: $(hdrdir)/ruby/internal/event.h -memory_view.o: $(hdrdir)/ruby/internal/fl_type.h -memory_view.o: $(hdrdir)/ruby/internal/gc.h -memory_view.o: $(hdrdir)/ruby/internal/glob.h -memory_view.o: $(hdrdir)/ruby/internal/globals.h -memory_view.o: $(hdrdir)/ruby/internal/has/attribute.h -memory_view.o: $(hdrdir)/ruby/internal/has/builtin.h -memory_view.o: $(hdrdir)/ruby/internal/has/c_attribute.h -memory_view.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -memory_view.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -memory_view.o: $(hdrdir)/ruby/internal/has/extension.h -memory_view.o: $(hdrdir)/ruby/internal/has/feature.h -memory_view.o: $(hdrdir)/ruby/internal/has/warning.h -memory_view.o: $(hdrdir)/ruby/internal/intern/array.h -memory_view.o: $(hdrdir)/ruby/internal/intern/bignum.h -memory_view.o: $(hdrdir)/ruby/internal/intern/class.h -memory_view.o: $(hdrdir)/ruby/internal/intern/compar.h -memory_view.o: $(hdrdir)/ruby/internal/intern/complex.h -memory_view.o: $(hdrdir)/ruby/internal/intern/cont.h -memory_view.o: $(hdrdir)/ruby/internal/intern/dir.h -memory_view.o: $(hdrdir)/ruby/internal/intern/enum.h -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/hash.h -memory_view.o: $(hdrdir)/ruby/internal/intern/io.h -memory_view.o: $(hdrdir)/ruby/internal/intern/load.h -memory_view.o: $(hdrdir)/ruby/internal/intern/marshal.h -memory_view.o: $(hdrdir)/ruby/internal/intern/numeric.h -memory_view.o: $(hdrdir)/ruby/internal/intern/object.h -memory_view.o: $(hdrdir)/ruby/internal/intern/parse.h -memory_view.o: $(hdrdir)/ruby/internal/intern/proc.h -memory_view.o: $(hdrdir)/ruby/internal/intern/process.h -memory_view.o: $(hdrdir)/ruby/internal/intern/random.h -memory_view.o: $(hdrdir)/ruby/internal/intern/range.h -memory_view.o: $(hdrdir)/ruby/internal/intern/rational.h -memory_view.o: $(hdrdir)/ruby/internal/intern/re.h -memory_view.o: $(hdrdir)/ruby/internal/intern/ruby.h -memory_view.o: $(hdrdir)/ruby/internal/intern/select.h -memory_view.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -memory_view.o: $(hdrdir)/ruby/internal/intern/signal.h -memory_view.o: $(hdrdir)/ruby/internal/intern/sprintf.h -memory_view.o: $(hdrdir)/ruby/internal/intern/string.h -memory_view.o: $(hdrdir)/ruby/internal/intern/struct.h -memory_view.o: $(hdrdir)/ruby/internal/intern/thread.h -memory_view.o: $(hdrdir)/ruby/internal/intern/time.h -memory_view.o: $(hdrdir)/ruby/internal/intern/variable.h -memory_view.o: $(hdrdir)/ruby/internal/intern/vm.h -memory_view.o: $(hdrdir)/ruby/internal/interpreter.h -memory_view.o: $(hdrdir)/ruby/internal/iterator.h -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/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 -memory_view.o: $(hdrdir)/ruby/internal/variable.h -memory_view.o: $(hdrdir)/ruby/internal/warning_push.h -memory_view.o: $(hdrdir)/ruby/internal/xmalloc.h -memory_view.o: $(hdrdir)/ruby/memory_view.h -memory_view.o: $(hdrdir)/ruby/missing.h -memory_view.o: $(hdrdir)/ruby/onigmo.h -memory_view.o: $(hdrdir)/ruby/oniguruma.h -memory_view.o: $(hdrdir)/ruby/ruby.h -memory_view.o: $(hdrdir)/ruby/st.h -memory_view.o: $(hdrdir)/ruby/subst.h -memory_view.o: closure.h -memory_view.o: conversions.h -memory_view.o: fiddle.h -memory_view.o: function.h -memory_view.o: memory_view.c -pinned.o: $(RUBY_EXTCONF_H) -pinned.o: $(arch_hdrdir)/ruby/config.h -pinned.o: $(hdrdir)/ruby.h -pinned.o: $(hdrdir)/ruby/assert.h -pinned.o: $(hdrdir)/ruby/backward.h -pinned.o: $(hdrdir)/ruby/backward/2/assume.h -pinned.o: $(hdrdir)/ruby/backward/2/attributes.h -pinned.o: $(hdrdir)/ruby/backward/2/bool.h -pinned.o: $(hdrdir)/ruby/backward/2/inttypes.h -pinned.o: $(hdrdir)/ruby/backward/2/limits.h -pinned.o: $(hdrdir)/ruby/backward/2/long_long.h -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 -pinned.o: $(hdrdir)/ruby/internal/arithmetic/double.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/int.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/long.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/short.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -pinned.o: $(hdrdir)/ruby/internal/assume.h -pinned.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -pinned.o: $(hdrdir)/ruby/internal/attr/artificial.h -pinned.o: $(hdrdir)/ruby/internal/attr/cold.h -pinned.o: $(hdrdir)/ruby/internal/attr/const.h -pinned.o: $(hdrdir)/ruby/internal/attr/constexpr.h -pinned.o: $(hdrdir)/ruby/internal/attr/deprecated.h -pinned.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -pinned.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -pinned.o: $(hdrdir)/ruby/internal/attr/error.h -pinned.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -pinned.o: $(hdrdir)/ruby/internal/attr/forceinline.h -pinned.o: $(hdrdir)/ruby/internal/attr/format.h -pinned.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -pinned.o: $(hdrdir)/ruby/internal/attr/noalias.h -pinned.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -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 -pinned.o: $(hdrdir)/ruby/internal/attr/warning.h -pinned.o: $(hdrdir)/ruby/internal/attr/weakref.h -pinned.o: $(hdrdir)/ruby/internal/cast.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -pinned.o: $(hdrdir)/ruby/internal/compiler_since.h -pinned.o: $(hdrdir)/ruby/internal/config.h -pinned.o: $(hdrdir)/ruby/internal/constant_p.h -pinned.o: $(hdrdir)/ruby/internal/core.h -pinned.o: $(hdrdir)/ruby/internal/core/rarray.h -pinned.o: $(hdrdir)/ruby/internal/core/rbasic.h -pinned.o: $(hdrdir)/ruby/internal/core/rbignum.h -pinned.o: $(hdrdir)/ruby/internal/core/rclass.h -pinned.o: $(hdrdir)/ruby/internal/core/rdata.h -pinned.o: $(hdrdir)/ruby/internal/core/rfile.h -pinned.o: $(hdrdir)/ruby/internal/core/rhash.h -pinned.o: $(hdrdir)/ruby/internal/core/robject.h -pinned.o: $(hdrdir)/ruby/internal/core/rregexp.h -pinned.o: $(hdrdir)/ruby/internal/core/rstring.h -pinned.o: $(hdrdir)/ruby/internal/core/rstruct.h -pinned.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -pinned.o: $(hdrdir)/ruby/internal/ctype.h -pinned.o: $(hdrdir)/ruby/internal/dllexport.h -pinned.o: $(hdrdir)/ruby/internal/dosish.h -pinned.o: $(hdrdir)/ruby/internal/error.h -pinned.o: $(hdrdir)/ruby/internal/eval.h -pinned.o: $(hdrdir)/ruby/internal/event.h -pinned.o: $(hdrdir)/ruby/internal/fl_type.h -pinned.o: $(hdrdir)/ruby/internal/gc.h -pinned.o: $(hdrdir)/ruby/internal/glob.h -pinned.o: $(hdrdir)/ruby/internal/globals.h -pinned.o: $(hdrdir)/ruby/internal/has/attribute.h -pinned.o: $(hdrdir)/ruby/internal/has/builtin.h -pinned.o: $(hdrdir)/ruby/internal/has/c_attribute.h -pinned.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -pinned.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -pinned.o: $(hdrdir)/ruby/internal/has/extension.h -pinned.o: $(hdrdir)/ruby/internal/has/feature.h -pinned.o: $(hdrdir)/ruby/internal/has/warning.h -pinned.o: $(hdrdir)/ruby/internal/intern/array.h -pinned.o: $(hdrdir)/ruby/internal/intern/bignum.h -pinned.o: $(hdrdir)/ruby/internal/intern/class.h -pinned.o: $(hdrdir)/ruby/internal/intern/compar.h -pinned.o: $(hdrdir)/ruby/internal/intern/complex.h -pinned.o: $(hdrdir)/ruby/internal/intern/cont.h -pinned.o: $(hdrdir)/ruby/internal/intern/dir.h -pinned.o: $(hdrdir)/ruby/internal/intern/enum.h -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/hash.h -pinned.o: $(hdrdir)/ruby/internal/intern/io.h -pinned.o: $(hdrdir)/ruby/internal/intern/load.h -pinned.o: $(hdrdir)/ruby/internal/intern/marshal.h -pinned.o: $(hdrdir)/ruby/internal/intern/numeric.h -pinned.o: $(hdrdir)/ruby/internal/intern/object.h -pinned.o: $(hdrdir)/ruby/internal/intern/parse.h -pinned.o: $(hdrdir)/ruby/internal/intern/proc.h -pinned.o: $(hdrdir)/ruby/internal/intern/process.h -pinned.o: $(hdrdir)/ruby/internal/intern/random.h -pinned.o: $(hdrdir)/ruby/internal/intern/range.h -pinned.o: $(hdrdir)/ruby/internal/intern/rational.h -pinned.o: $(hdrdir)/ruby/internal/intern/re.h -pinned.o: $(hdrdir)/ruby/internal/intern/ruby.h -pinned.o: $(hdrdir)/ruby/internal/intern/select.h -pinned.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -pinned.o: $(hdrdir)/ruby/internal/intern/signal.h -pinned.o: $(hdrdir)/ruby/internal/intern/sprintf.h -pinned.o: $(hdrdir)/ruby/internal/intern/string.h -pinned.o: $(hdrdir)/ruby/internal/intern/struct.h -pinned.o: $(hdrdir)/ruby/internal/intern/thread.h -pinned.o: $(hdrdir)/ruby/internal/intern/time.h -pinned.o: $(hdrdir)/ruby/internal/intern/variable.h -pinned.o: $(hdrdir)/ruby/internal/intern/vm.h -pinned.o: $(hdrdir)/ruby/internal/interpreter.h -pinned.o: $(hdrdir)/ruby/internal/iterator.h -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/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 -pinned.o: $(hdrdir)/ruby/internal/variable.h -pinned.o: $(hdrdir)/ruby/internal/warning_push.h -pinned.o: $(hdrdir)/ruby/internal/xmalloc.h -pinned.o: $(hdrdir)/ruby/missing.h -pinned.o: $(hdrdir)/ruby/ruby.h -pinned.o: $(hdrdir)/ruby/st.h -pinned.o: $(hdrdir)/ruby/subst.h -pinned.o: closure.h -pinned.o: conversions.h -pinned.o: fiddle.h -pinned.o: function.h -pinned.o: pinned.c -pointer.o: $(RUBY_EXTCONF_H) -pointer.o: $(arch_hdrdir)/ruby/config.h -pointer.o: $(hdrdir)/ruby.h -pointer.o: $(hdrdir)/ruby/assert.h -pointer.o: $(hdrdir)/ruby/backward.h -pointer.o: $(hdrdir)/ruby/backward/2/assume.h -pointer.o: $(hdrdir)/ruby/backward/2/attributes.h -pointer.o: $(hdrdir)/ruby/backward/2/bool.h -pointer.o: $(hdrdir)/ruby/backward/2/inttypes.h -pointer.o: $(hdrdir)/ruby/backward/2/limits.h -pointer.o: $(hdrdir)/ruby/backward/2/long_long.h -pointer.o: $(hdrdir)/ruby/backward/2/stdalign.h -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 -pointer.o: $(hdrdir)/ruby/internal/arithmetic/double.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/int.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/long.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/short.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -pointer.o: $(hdrdir)/ruby/internal/assume.h -pointer.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -pointer.o: $(hdrdir)/ruby/internal/attr/artificial.h -pointer.o: $(hdrdir)/ruby/internal/attr/cold.h -pointer.o: $(hdrdir)/ruby/internal/attr/const.h -pointer.o: $(hdrdir)/ruby/internal/attr/constexpr.h -pointer.o: $(hdrdir)/ruby/internal/attr/deprecated.h -pointer.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -pointer.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -pointer.o: $(hdrdir)/ruby/internal/attr/error.h -pointer.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -pointer.o: $(hdrdir)/ruby/internal/attr/forceinline.h -pointer.o: $(hdrdir)/ruby/internal/attr/format.h -pointer.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -pointer.o: $(hdrdir)/ruby/internal/attr/noalias.h -pointer.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -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 -pointer.o: $(hdrdir)/ruby/internal/attr/warning.h -pointer.o: $(hdrdir)/ruby/internal/attr/weakref.h -pointer.o: $(hdrdir)/ruby/internal/cast.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -pointer.o: $(hdrdir)/ruby/internal/compiler_since.h -pointer.o: $(hdrdir)/ruby/internal/config.h -pointer.o: $(hdrdir)/ruby/internal/constant_p.h -pointer.o: $(hdrdir)/ruby/internal/core.h -pointer.o: $(hdrdir)/ruby/internal/core/rarray.h -pointer.o: $(hdrdir)/ruby/internal/core/rbasic.h -pointer.o: $(hdrdir)/ruby/internal/core/rbignum.h -pointer.o: $(hdrdir)/ruby/internal/core/rclass.h -pointer.o: $(hdrdir)/ruby/internal/core/rdata.h -pointer.o: $(hdrdir)/ruby/internal/core/rfile.h -pointer.o: $(hdrdir)/ruby/internal/core/rhash.h -pointer.o: $(hdrdir)/ruby/internal/core/robject.h -pointer.o: $(hdrdir)/ruby/internal/core/rregexp.h -pointer.o: $(hdrdir)/ruby/internal/core/rstring.h -pointer.o: $(hdrdir)/ruby/internal/core/rstruct.h -pointer.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -pointer.o: $(hdrdir)/ruby/internal/ctype.h -pointer.o: $(hdrdir)/ruby/internal/dllexport.h -pointer.o: $(hdrdir)/ruby/internal/dosish.h -pointer.o: $(hdrdir)/ruby/internal/encoding/coderange.h -pointer.o: $(hdrdir)/ruby/internal/encoding/ctype.h -pointer.o: $(hdrdir)/ruby/internal/encoding/encoding.h -pointer.o: $(hdrdir)/ruby/internal/encoding/pathname.h -pointer.o: $(hdrdir)/ruby/internal/encoding/re.h -pointer.o: $(hdrdir)/ruby/internal/encoding/sprintf.h -pointer.o: $(hdrdir)/ruby/internal/encoding/string.h -pointer.o: $(hdrdir)/ruby/internal/encoding/symbol.h -pointer.o: $(hdrdir)/ruby/internal/encoding/transcode.h -pointer.o: $(hdrdir)/ruby/internal/error.h -pointer.o: $(hdrdir)/ruby/internal/eval.h -pointer.o: $(hdrdir)/ruby/internal/event.h -pointer.o: $(hdrdir)/ruby/internal/fl_type.h -pointer.o: $(hdrdir)/ruby/internal/gc.h -pointer.o: $(hdrdir)/ruby/internal/glob.h -pointer.o: $(hdrdir)/ruby/internal/globals.h -pointer.o: $(hdrdir)/ruby/internal/has/attribute.h -pointer.o: $(hdrdir)/ruby/internal/has/builtin.h -pointer.o: $(hdrdir)/ruby/internal/has/c_attribute.h -pointer.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -pointer.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -pointer.o: $(hdrdir)/ruby/internal/has/extension.h -pointer.o: $(hdrdir)/ruby/internal/has/feature.h -pointer.o: $(hdrdir)/ruby/internal/has/warning.h -pointer.o: $(hdrdir)/ruby/internal/intern/array.h -pointer.o: $(hdrdir)/ruby/internal/intern/bignum.h -pointer.o: $(hdrdir)/ruby/internal/intern/class.h -pointer.o: $(hdrdir)/ruby/internal/intern/compar.h -pointer.o: $(hdrdir)/ruby/internal/intern/complex.h -pointer.o: $(hdrdir)/ruby/internal/intern/cont.h -pointer.o: $(hdrdir)/ruby/internal/intern/dir.h -pointer.o: $(hdrdir)/ruby/internal/intern/enum.h -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/hash.h -pointer.o: $(hdrdir)/ruby/internal/intern/io.h -pointer.o: $(hdrdir)/ruby/internal/intern/load.h -pointer.o: $(hdrdir)/ruby/internal/intern/marshal.h -pointer.o: $(hdrdir)/ruby/internal/intern/numeric.h -pointer.o: $(hdrdir)/ruby/internal/intern/object.h -pointer.o: $(hdrdir)/ruby/internal/intern/parse.h -pointer.o: $(hdrdir)/ruby/internal/intern/proc.h -pointer.o: $(hdrdir)/ruby/internal/intern/process.h -pointer.o: $(hdrdir)/ruby/internal/intern/random.h -pointer.o: $(hdrdir)/ruby/internal/intern/range.h -pointer.o: $(hdrdir)/ruby/internal/intern/rational.h -pointer.o: $(hdrdir)/ruby/internal/intern/re.h -pointer.o: $(hdrdir)/ruby/internal/intern/ruby.h -pointer.o: $(hdrdir)/ruby/internal/intern/select.h -pointer.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -pointer.o: $(hdrdir)/ruby/internal/intern/signal.h -pointer.o: $(hdrdir)/ruby/internal/intern/sprintf.h -pointer.o: $(hdrdir)/ruby/internal/intern/string.h -pointer.o: $(hdrdir)/ruby/internal/intern/struct.h -pointer.o: $(hdrdir)/ruby/internal/intern/thread.h -pointer.o: $(hdrdir)/ruby/internal/intern/time.h -pointer.o: $(hdrdir)/ruby/internal/intern/variable.h -pointer.o: $(hdrdir)/ruby/internal/intern/vm.h -pointer.o: $(hdrdir)/ruby/internal/interpreter.h -pointer.o: $(hdrdir)/ruby/internal/iterator.h -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/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 -pointer.o: $(hdrdir)/ruby/internal/variable.h -pointer.o: $(hdrdir)/ruby/internal/warning_push.h -pointer.o: $(hdrdir)/ruby/internal/xmalloc.h -pointer.o: $(hdrdir)/ruby/io.h -pointer.o: $(hdrdir)/ruby/memory_view.h -pointer.o: $(hdrdir)/ruby/missing.h -pointer.o: $(hdrdir)/ruby/onigmo.h -pointer.o: $(hdrdir)/ruby/oniguruma.h -pointer.o: $(hdrdir)/ruby/ruby.h -pointer.o: $(hdrdir)/ruby/st.h -pointer.o: $(hdrdir)/ruby/subst.h -pointer.o: closure.h -pointer.o: conversions.h -pointer.o: fiddle.h -pointer.o: function.h -pointer.o: pointer.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb deleted file mode 100644 index 36e9bd56cb..0000000000 --- a/ext/fiddle/extconf.rb +++ /dev/null @@ -1,266 +0,0 @@ -# frozen_string_literal: true - -require "rbconfig" - -unless RUBY_ENGINE == "ruby" - File.write('Makefile', <<-MAKEFILE) -all install clean: - #{RbConfig::CONFIG["NULLCMD"]} - -.PHONY: all install clean - MAKEFILE - return -end - -require 'mkmf' - -# :stopdoc: - -def gcc? - RbConfig::CONFIG["GCC"] == "yes" -end - -def disable_optimization_build_flag(flags) - if gcc? - expanded_flags = RbConfig.expand(flags.dup) - optimization_option_pattern = /(^|\s)?-O\d(\s|$)?/ - if optimization_option_pattern.match?(expanded_flags) - expanded_flags.gsub(optimization_option_pattern, '\\1-Og\\2') - else - flags + " -Og" - end - else - flags - end -end - -def enable_debug_build_flag(flags) - if gcc? - expanded_flags = RbConfig.expand(flags.dup) - debug_option_pattern = /(^|\s)-g(?:gdb)?\d?(\s|$)/ - if debug_option_pattern.match?(expanded_flags) - expanded_flags.gsub(debug_option_pattern, '\\1-ggdb3\\2') - else - flags + " -ggdb3" - end - else - flags - end -end - -checking_for(checking_message("--enable-debug-build option")) do - enable_debug_build = enable_config("debug-build", false) - if enable_debug_build - $CFLAGS = disable_optimization_build_flag($CFLAGS) - $CFLAGS = enable_debug_build_flag($CFLAGS) - end - enable_debug_build -end - -libffi_version = nil -have_libffi = false -bundle = with_config("libffi-source-dir") -unless bundle - dir_config 'libffi' - - if pkg_config("libffi") - libffi_version = pkg_config("libffi", "modversion") - end - - have_ffi_header = false - if have_header(ffi_header = 'ffi.h') - have_ffi_header = true - elsif have_header(ffi_header = 'ffi/ffi.h') - $defs.push('-DUSE_HEADER_HACKS') - have_ffi_header = true - end - if have_ffi_header && (have_library('ffi') || have_library('libffi')) - have_libffi = true - end -end - -unless have_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 - ffi_header = 'ffi.h' - libffi = Struct.new(*%I[dir srcdir builddir include lib a cflags ldflags opt arch]).new - libffi.dir = libffi_package_name - if $srcdir == "." - libffi.builddir = libffi_package_name - libffi.srcdir = "." - else - libffi.builddir = libffi.dir - libffi.srcdir = relative_from(libffi_srcdir, "..") - end - libffi.include = "#{libffi.builddir}/include" - libffi.lib = "#{libffi.builddir}/.libs" - libffi.a = "#{libffi.lib}/libffi_convenience.#{$LIBEXT}" - nowarn = CONFIG.merge("warnflags"=>"") - libffi.cflags = RbConfig.expand("$(CFLAGS)".dup, nowarn) - libffi_version = libffi_package_name[/libffi-(.*)/, 1] - - FileUtils.mkdir_p(libffi.dir) - libffi.opt = CONFIG['configure_args'][/'(-C)'/, 1] - libffi.ldflags = RbConfig.expand("$(LDFLAGS) #{libpathflag([relative_from($topdir, "..")])} #{$LIBRUBYARG}".dup) - libffi.arch = RbConfig::CONFIG['host'] - if $mswin - unless find_executable(as = /x64/ =~ libffi.arch ? "ml64" : "ml") - raise "missing #{as} command." - end - $defs << "-DFFI_BUILDING" - libffi_config = "#{relative_from($srcdir, '..')}/win32/libffi-config.rb" - config = CONFIG.merge("top_srcdir" => $top_srcdir) - args = $ruby.gsub(/:\/=\\/, '') - args.gsub!(/\)\\/, ')/') - args = args.shellsplit - args.map! {|s| RbConfig.expand(s, config)} - args << '-C' << libffi.dir << libffi_config - opts = {} - else - args = %W[sh #{libffi.srcdir}/configure ] - opts = {chdir: libffi.dir} - end - cc = RbConfig::CONFIG['CC'] - cxx = RbConfig::CONFIG['CXX'] - ld = RbConfig::CONFIG['LD'] - args.concat %W[ - --srcdir=#{libffi.srcdir} - --host=#{libffi.arch} - ] - args << ($enable_shared || !$static ? '--enable-shared' : '--enable-static') - args << libffi.opt if libffi.opt - args.concat %W[ - CC=#{cc} CFLAGS=#{libffi.cflags} - CXX=#{cxx} CXXFLAGS=#{RbConfig.expand("$(CXXFLAGS)".dup, nowarn)} - LD=#{ld} LDFLAGS=#{libffi.ldflags} - ] - - FileUtils.rm_f("#{libffi.include}/ffitarget.h") - Logging::open do - Logging.message("%p in %p\n", args, opts) - unless system(*args, **opts) - begin - IO.copy_stream(libffi.dir + "/config.log", Logging.instance_variable_get(:@logfile)) - rescue SystemCallError => e - Logging.message("%s\n", e.message) - end - raise "failed to configure libffi. Please install libffi." - end - end - if $mswin && File.file?("#{libffi.include}/ffitarget.h") - FileUtils.rm_f("#{libffi.include}/ffitarget.h") - end - unless File.file?("#{libffi.include}/ffitarget.h") - FileUtils.cp("#{libffi_srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true) - end - $INCFLAGS << " -I" << libffi.include -end - -if libffi_version - # If libffi_version contains rc version, just ignored. - 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 }}) - warn "libffi_version: #{libffi_version.join('.')}" -end - -case -when $mswin, $mingw, (libffi_version && (libffi_version <=> [3, 2]) >= 0) - $defs << "-DUSE_FFI_CLOSURE_ALLOC=1" -when (libffi_version && (libffi_version <=> [3, 2]) < 0) -else - have_func('ffi_closure_alloc', ffi_header) -end - -if libffi_version - if (libffi_version <=> [3, 0, 11]) >= 0 - $defs << "-DHAVE_FFI_PREP_CIF_VAR" - end -else - have_func('ffi_prep_cif_var', ffi_header) -end - -have_header 'sys/mman.h' -have_header 'link.h' - -if have_header "dlfcn.h" - have_library "dl" - - %w{ dlopen dlclose dlsym }.each do |func| - abort "missing function #{func}" unless have_func(func) - end - - have_func "dlerror" - have_func "dlinfo" - have_const("RTLD_DI_LINKMAP", "dlfcn.h") -elsif have_header "windows.h" - %w{ LoadLibrary FreeLibrary GetProcAddress GetModuleFileName }.each do |func| - abort "missing function #{func}" unless have_func(func) - end - - have_library "ws2_32" -end - -have_const('FFI_STDCALL', ffi_header) - -config = File.read(RbConfig.expand(File.join($arch_hdrdir, "ruby/config.h"))) -types = {"SIZE_T"=>"SSIZE_T", "PTRDIFF_T"=>nil, "INTPTR_T"=>nil} -types.each do |type, signed| - if /^\#define\s+SIZEOF_#{type}\s+(SIZEOF_(.+)|\d+)/ =~ config - if size = $2 and size != 'VOIDP' - size = types.fetch(size) {size} - $defs << "-DTYPE_#{signed||type}=TYPE_#{size}" - end - if signed - check_signedness(type.downcase, "stddef.h") - end - else - check_signedness(type.downcase, "stddef.h") - end -end - -if libffi - $LOCAL_LIBS.prepend("#{libffi.a} ").strip! # to exts.mk - $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)') -end - -have_func("rb_str_to_interned_str") -create_makefile 'fiddle' do |conf| - if !libffi - next conf << "LIBFFI_CLEAN = none\n" - elsif $gnumake && !$nmake - submake_arg = "-C $(LIBFFI_DIR)\n" - else - submake_pre = "cd $(LIBFFI_DIR) && #{config_string("exec")}".strip - end - if $nmake - cmd = "$(RUBY) -C $(LIBFFI_DIR) #{libffi_config} --srcdir=$(LIBFFI_SRCDIR)" - else - cmd = "cd $(LIBFFI_DIR) && #$exec $(LIBFFI_SRCDIR)/configure #{libffi.opt}" - end - sep = "/" - seprpl = config_string('BUILD_FILE_SEPARATOR') {|s| sep = s; ":/=#{s}" if s != "/"} || "" - conf << <<-MK.gsub(/^ +| +$/, '') - PWD = - LIBFFI_CONFIGURE = #{cmd} - LIBFFI_ARCH = #{libffi.arch} - LIBFFI_SRCDIR = #{libffi.srcdir.sub(libffi.dir, '$(LIBFFI_DIR)')} - LIBFFI_DIR = #{libffi.dir} - LIBFFI_A = #{libffi.a.sub(libffi.dir, '$(LIBFFI_DIR)')} - LIBFFI_CFLAGS = #{libffi.cflags} - LIBFFI_LDFLAGS = #{libffi.ldflags} - FFI_H = $(LIBFFI_DIR)/include/ffi.h - SUBMAKE_PRE = #{submake_pre} - SUBMAKE_ARG = #{submake_arg} - LIBFFI_CLEAN = libffi - MK -end - -if libffi - $LIBPATH.pop -end - -# :startdoc: diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c deleted file mode 100644 index 91a998813a..0000000000 --- a/ext/fiddle/fiddle.c +++ /dev/null @@ -1,711 +0,0 @@ -#include <stdbool.h> - -#include <fiddle.h> - -VALUE mFiddle; -VALUE rb_eFiddleDLError; -VALUE rb_eFiddleError; - -void Init_fiddle_pointer(void); -void Init_fiddle_pinned(void); - -#ifdef HAVE_RUBY_MEMORY_VIEW_H -void Init_fiddle_memory_view(void); -#endif - -/* - * call-seq: Fiddle.malloc(size) - * - * Allocate +size+ bytes of memory and return the integer memory address - * for the allocated memory. - */ -static VALUE -rb_fiddle_malloc(VALUE self, VALUE size) -{ - void *ptr; - ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size)); - return PTR2NUM(ptr); -} - -/* - * call-seq: Fiddle.realloc(addr, size) - * - * Change the size of the memory allocated at the memory location +addr+ to - * +size+ bytes. Returns the memory address of the reallocated memory, which - * may be different than the address passed in. - */ -static VALUE -rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size) -{ - void *ptr = NUM2PTR(addr); - - ptr = (void*)ruby_xrealloc(ptr, NUM2SIZET(size)); - return PTR2NUM(ptr); -} - -/* - * call-seq: Fiddle.free(addr) - * - * Free the memory at address +addr+ - */ -VALUE -rb_fiddle_free(VALUE self, VALUE addr) -{ - void *ptr = NUM2PTR(addr); - - ruby_xfree(ptr); - return Qnil; -} - -/* - * call-seq: Fiddle.dlunwrap(addr) - * - * Returns the Ruby object stored at the memory address +addr+ - * - * Example: - * - * x = Object.new - * # => #<Object:0x0000000107c7d870> - * Fiddle.dlwrap(x) - * # => 4425504880 - * Fiddle.dlunwrap(_) - * # => #<Object:0x0000000107c7d870> - */ -VALUE -rb_fiddle_ptr2value(VALUE self, VALUE addr) -{ - return (VALUE)NUM2PTR(addr); -} - -/* - * call-seq: Fiddle.dlwrap(val) - * - * Returns the memory address of the Ruby object stored at +val+ - * - * Example: - * - * 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(123) - * # => 247 - */ -static VALUE -rb_fiddle_value2ptr(VALUE self, VALUE val) -{ - return PTR2NUM((void*)val); -} - -void Init_fiddle_handle(void); - -void -Init_fiddle(void) -{ - /* - * Document-module: Fiddle - * - * A libffi wrapper for Ruby. - * - * == Description - * - * Fiddle is an extension to translate a foreign function interface (FFI) - * with ruby. - * - * It wraps {libffi}[http://sourceware.org/libffi/], a popular C library - * which provides a portable interface that allows code written in one - * language to call code written in another language. - * - * == Example - * - * Here we will use Fiddle::Function to wrap {floor(3) from - * libm}[http://linux.die.net/man/3/floor] - * - * require 'fiddle' - * - * libm = Fiddle.dlopen('/lib/libm.so.6') - * - * floor = Fiddle::Function.new( - * libm['floor'], - * [Fiddle::TYPE_DOUBLE], - * Fiddle::TYPE_DOUBLE - * ) - * - * puts floor.call(3.14159) #=> 3.0 - * - * - */ - mFiddle = rb_define_module("Fiddle"); - - /* - * Document-class: Fiddle::Error - * - * Generic error class for Fiddle - */ - rb_eFiddleError = rb_define_class_under(mFiddle, "Error", rb_eStandardError); - - /* - * Ruby installed by RubyInstaller for Windows always require - * bundled Fiddle because ruby_installer/runtime/dll_directory.rb - * requires Fiddle. It's used by - * rubygems/defaults/operating_system.rb. It means that the - * bundled Fiddle is always required on initialization. - * - * We just remove existing Fiddle::DLError here to override - * the bundled Fiddle. - */ - if (rb_const_defined(mFiddle, rb_intern("DLError"))) { - rb_const_remove(mFiddle, rb_intern("DLError")); - } - - /* - * Document-class: Fiddle::DLError - * - * standard dynamic load exception - */ - rb_eFiddleDLError = rb_define_class_under(mFiddle, "DLError", rb_eFiddleError); - - VALUE mFiddleTypes = rb_define_module_under(mFiddle, "Types"); - - /* Document-const: Fiddle::Types::VOID - * - * C type - void - */ - rb_define_const(mFiddleTypes, "VOID", INT2NUM(TYPE_VOID)); - - /* Document-const: Fiddle::Types::VOIDP - * - * C type - void* - */ - rb_define_const(mFiddleTypes, "VOIDP", INT2NUM(TYPE_VOIDP)); - - /* Document-const: Fiddle::Types::CHAR - * - * C type - char - */ - rb_define_const(mFiddleTypes, "CHAR", INT2NUM(TYPE_CHAR)); - - /* 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(mFiddleTypes, "SHORT", INT2NUM(TYPE_SHORT)); - - /* 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(mFiddleTypes, "INT", INT2NUM(TYPE_INT)); - - /* Document-const: Fiddle::Types::UINT - * - * C type - unsigned int - */ - rb_define_const(mFiddleTypes, "UINT", INT2NUM(TYPE_UINT)); - - /* Document-const: Fiddle::Types::LONG - * - * C 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: 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(mFiddleTypes, "ULONG_LONG", INT2NUM(TYPE_ULONG_LONG)); -#endif - -#ifdef TYPE_INT8_T - /* Document-const: Fiddle::Types::INT8_T - * - * C 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: Fiddle::Types::INT16_T - * - * C 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: Fiddle::Types::INT32_T - * - * C 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: Fiddle::Types::INT64_T - * - * C 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: Fiddle::Types::FLOAT - * - * C type - float - */ - rb_define_const(mFiddleTypes, "FLOAT", INT2NUM(TYPE_FLOAT)); - - /* Document-const: Fiddle::Types::DOUBLE - * - * C type - double - */ - rb_define_const(mFiddleTypes, "DOUBLE", INT2NUM(TYPE_DOUBLE)); - -#ifdef HAVE_FFI_PREP_CIF_VAR - /* Document-const: Fiddle::Types::VARIADIC - * - * C type - ... - */ - rb_define_const(mFiddleTypes, "VARIADIC", INT2NUM(TYPE_VARIADIC)); -#endif - - /* Document-const: Fiddle::Types::CONST_STRING - * - * C type - const char* ('\0' terminated const char*) - */ - rb_define_const(mFiddleTypes, "CONST_STRING", INT2NUM(TYPE_CONST_STRING)); - - /* Document-const: Fiddle::Types::SIZE_T - * - * C type - size_t - */ - rb_define_const(mFiddleTypes, "SIZE_T", INT2NUM(TYPE_SIZE_T)); - - /* Document-const: Fiddle::Types::SSIZE_T - * - * C type - ssize_t - */ - rb_define_const(mFiddleTypes, "SSIZE_T", INT2NUM(TYPE_SSIZE_T)); - - /* Document-const: Fiddle::Types::PTRDIFF_T - * - * C type - ptrdiff_t - */ - rb_define_const(mFiddleTypes, "PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T)); - - /* Document-const: Fiddle::Types::INTPTR_T - * - * C type - intptr_t - */ - rb_define_const(mFiddleTypes, "INTPTR_T", INT2NUM(TYPE_INTPTR_T)); - - /* Document-const: Fiddle::Types::UINTPTR_T - * - * C 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 - * - * The alignment size of a void* - */ - rb_define_const(mFiddle, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP)); - - /* Document-const: ALIGN_CHAR - * - * The alignment size of a char - */ - rb_define_const(mFiddle, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR)); - - /* Document-const: ALIGN_SHORT - * - * The alignment size of a short - */ - rb_define_const(mFiddle, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT)); - - /* Document-const: ALIGN_INT - * - * The alignment size of an int - */ - rb_define_const(mFiddle, "ALIGN_INT", INT2NUM(ALIGN_INT)); - - /* Document-const: ALIGN_LONG - * - * The alignment size of a long - */ - rb_define_const(mFiddle, "ALIGN_LONG", INT2NUM(ALIGN_LONG)); - -#if HAVE_LONG_LONG - /* Document-const: ALIGN_LONG_LONG - * - * The alignment size of a long long - */ - rb_define_const(mFiddle, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG)); -#endif - - /* Document-const: ALIGN_INT8_T - * - * The alignment size of a int8_t - */ - rb_define_const(mFiddle, "ALIGN_INT8_T", INT2NUM(ALIGN_INT8_T)); - - /* Document-const: ALIGN_INT16_T - * - * The alignment size of a int16_t - */ - rb_define_const(mFiddle, "ALIGN_INT16_T", INT2NUM(ALIGN_INT16_T)); - - /* Document-const: ALIGN_INT32_T - * - * The alignment size of a int32_t - */ - rb_define_const(mFiddle, "ALIGN_INT32_T", INT2NUM(ALIGN_INT32_T)); - - /* Document-const: ALIGN_INT64_T - * - * The alignment size of a int64_t - */ - rb_define_const(mFiddle, "ALIGN_INT64_T", INT2NUM(ALIGN_INT64_T)); - - /* Document-const: ALIGN_FLOAT - * - * The alignment size of a float - */ - rb_define_const(mFiddle, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT)); - - /* Document-const: ALIGN_DOUBLE - * - * The alignment size of a double - */ - rb_define_const(mFiddle, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE)); - - /* Document-const: ALIGN_SIZE_T - * - * The alignment size of a size_t - */ - rb_define_const(mFiddle, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t))); - - /* Document-const: ALIGN_SSIZE_T - * - * The alignment size of a ssize_t - */ - rb_define_const(mFiddle, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */ - - /* Document-const: ALIGN_PTRDIFF_T - * - * The alignment size of a ptrdiff_t - */ - rb_define_const(mFiddle, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t))); - - /* Document-const: ALIGN_INTPTR_T - * - * The alignment size of a intptr_t - */ - rb_define_const(mFiddle, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t))); - - /* Document-const: ALIGN_UINTPTR_T - * - * The alignment size of a uintptr_t - */ - 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 - */ -#if defined(_WIN32) - rb_define_const(mFiddle, "WINDOWS", Qtrue); -#else - rb_define_const(mFiddle, "WINDOWS", Qfalse); -#endif - - /* Document-const: SIZEOF_VOIDP - * - * size of a void* - */ - rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*))); - - /* Document-const: SIZEOF_CHAR - * - * size of a char - */ - 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 - * - * size of a int8_t - */ - 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 - */ - rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float))); - - /* Document-const: SIZEOF_DOUBLE - * - * size of a double - */ - rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double))); - - /* Document-const: SIZEOF_SIZE_T - * - * size of a size_t - */ - rb_define_const(mFiddle, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t))); - - /* Document-const: SIZEOF_SSIZE_T - * - * size of a ssize_t - */ - rb_define_const(mFiddle, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */ - - /* Document-const: SIZEOF_PTRDIFF_T - * - * size of a ptrdiff_t - */ - rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t))); - - /* Document-const: SIZEOF_INTPTR_T - * - * size of a intptr_t - */ - rb_define_const(mFiddle, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t))); - - /* Document-const: SIZEOF_UINTPTR_T - * - * size of a uintptr_t - */ - rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t))); - - /* Document-const: SIZEOF_CONST_STRING - * - * size of a const char* - */ - 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 - */ - rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree)); - - /* Document-const: BUILD_RUBY_PLATFORM - * - * Platform built against (i.e. "x86_64-linux", etc.) - * - * See also RUBY_PLATFORM - */ - rb_define_const(mFiddle, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM)); - - rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1); - rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1); - rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1); - 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(); - Init_fiddle_pointer(); - Init_fiddle_pinned(); - -#ifdef HAVE_RUBY_MEMORY_VIEW_H - Init_fiddle_memory_view(); -#endif -} diff --git a/ext/fiddle/fiddle.gemspec b/ext/fiddle/fiddle.gemspec deleted file mode 100644 index 0092f52003..0000000000 --- a/ext/fiddle/fiddle.gemspec +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true - -version_module = Module.new do - version_rb = File.join(__dir__, "lib/fiddle/version.rb") - module_eval(File.read(version_rb), version_rb, __LINE__) -end - -Gem::Specification.new do |spec| - spec.name = "fiddle" - spec.version = version_module::Fiddle::VERSION - spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"] - spec.email = ["[email protected]", "[email protected]"] - - spec.summary = %q{A libffi wrapper for Ruby.} - spec.description = %q{A libffi wrapper for Ruby.} - spec.homepage = "https://github.com/ruby/fiddle" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.files = [ - "LICENSE.txt", - "README.md", - "Rakefile", - "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/fiddle.c", - "ext/fiddle/fiddle.h", - "ext/fiddle/function.c", - "ext/fiddle/function.h", - "ext/fiddle/handle.c", - "ext/fiddle/memory_view.c", - "ext/fiddle/pinned.c", - "ext/fiddle/pointer.c", - "fiddle.gemspec", - "lib/fiddle.rb", - "lib/fiddle/closure.rb", - "lib/fiddle/cparser.rb", - "lib/fiddle/ffi_backend.rb", - "lib/fiddle/function.rb", - "lib/fiddle/import.rb", - "lib/fiddle/pack.rb", - "lib/fiddle/struct.rb", - "lib/fiddle/types.rb", - "lib/fiddle/value.rb", - "lib/fiddle/version.rb", - ] - spec.require_paths = ["lib"] - spec.extensions = ["ext/fiddle/extconf.rb"] - - 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 deleted file mode 100644 index 49cc602367..0000000000 --- a/ext/fiddle/fiddle.h +++ /dev/null @@ -1,250 +0,0 @@ -#ifndef FIDDLE_H -#define FIDDLE_H - -#include <ruby.h> -#include <errno.h> - -#if defined(_WIN32) -#include <windows.h> -#endif - -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif - -#if defined(HAVE_LINK_H) -# include <link.h> -#endif - -#if defined(HAVE_DLFCN_H) -# include <dlfcn.h> -# /* some stranger systems may not define all of these */ -#ifndef RTLD_LAZY -#define RTLD_LAZY 0 -#endif -#ifndef RTLD_GLOBAL -#define RTLD_GLOBAL 0 -#endif -#ifndef RTLD_NOW -#define RTLD_NOW 0 -#endif -#else -# if defined(_WIN32) -# include <windows.h> -# define dlopen(name,flag) ((void*)LoadLibrary(name)) -# define dlerror() strerror(rb_w32_map_errno(GetLastError())) -# define dlsym(handle,name) ((void*)GetProcAddress((handle),(name))) -# define RTLD_LAZY -1 -# define RTLD_NOW -1 -# define RTLD_GLOBAL -1 -# endif -#endif - -#define FFI_GO_CLOSURES 0 /* fiddle does not use go closures */ -#ifdef USE_HEADER_HACKS -#include <ffi/ffi.h> -#else -#include <ffi.h> -#endif - -#undef ffi_type_uchar -#undef ffi_type_schar -#undef ffi_type_ushort -#undef ffi_type_sshort -#undef ffi_type_uint -#undef ffi_type_sint -#undef ffi_type_ulong -#undef ffi_type_slong - -#if CHAR_BIT == 8 -# define ffi_type_uchar ffi_type_uint8 -# define ffi_type_schar ffi_type_sint8 -#else -# error "CHAR_BIT not supported" -#endif - -#if SIZEOF_SHORT == 2 -# define ffi_type_ushort ffi_type_uint16 -# define ffi_type_sshort ffi_type_sint16 -#elif SIZEOF_SHORT == 4 -# define ffi_type_ushort ffi_type_uint32 -# define ffi_type_sshort ffi_type_sint32 -#else -# error "short size not supported" -#endif - -#if SIZEOF_INT == 2 -# define ffi_type_uint ffi_type_uint16 -# define ffi_type_sint ffi_type_sint16 -#elif SIZEOF_INT == 4 -# define ffi_type_uint ffi_type_uint32 -# define ffi_type_sint ffi_type_sint32 -#elif SIZEOF_INT == 8 -# define ffi_type_uint ffi_type_uint64 -# define ffi_type_sint ffi_type_sint64 -#else -# error "int size not supported" -#endif - -#if SIZEOF_LONG == 4 -# define ffi_type_ulong ffi_type_uint32 -# define ffi_type_slong ffi_type_sint32 -#elif SIZEOF_LONG == 8 -# define ffi_type_ulong ffi_type_uint64 -# define ffi_type_slong ffi_type_sint64 -#else -# error "long size not supported" -#endif - -#if HAVE_LONG_LONG -# if SIZEOF_LONG_LONG == 8 -# define ffi_type_slong_long ffi_type_sint64 -# define ffi_type_ulong_long ffi_type_uint64 -# else -# error "long long size not supported" -# endif -#endif - -#include <closure.h> -#include <conversions.h> -#include <function.h> - -#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 -#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 -# define TYPE_INT32_T TYPE_INT -#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 -# define TYPE_INT64_T TYPE_LONG -#elif defined(TYPE_LONG_LONG) -# 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 -# elif SIZEOF_SIZE_T == SIZEOF_LONG -# define TYPE_SSIZE_T TYPE_LONG -# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG -# define TYPE_SSIZE_T TYPE_LONG_LONG -# endif -#endif -#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T) - -#ifndef TYPE_PTRDIFF_T -# if SIZEOF_PTRDIFF_T == SIZEOF_INT -# define TYPE_PTRDIFF_T TYPE_INT -# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG -# define TYPE_PTRDIFF_T TYPE_LONG -# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG -# define TYPE_PTRDIFF_T TYPE_LONG_LONG -# endif -#endif - -#ifndef TYPE_INTPTR_T -# if SIZEOF_INTPTR_T == SIZEOF_INT -# define TYPE_INTPTR_T TYPE_INT -# elif SIZEOF_INTPTR_T == SIZEOF_LONG -# define TYPE_INTPTR_T TYPE_LONG -# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG -# define TYPE_INTPTR_T TYPE_LONG_LONG -# endif -#endif -#define TYPE_UINTPTR_T (-TYPE_INTPTR_T) - -/* 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) -#define ALIGN_SHORT ALIGN_OF(short) -#define ALIGN_INT ALIGN_OF(int) -#define ALIGN_LONG ALIGN_OF(long) -#if HAVE_LONG_LONG -#define ALIGN_LONG_LONG ALIGN_OF(LONG_LONG) -#endif -#define ALIGN_FLOAT ALIGN_OF(float) -#define ALIGN_DOUBLE ALIGN_OF(double) - -#define ALIGN_INT8_T ALIGN_OF(int8_t) -#define ALIGN_INT16_T ALIGN_OF(int16_t) -#define ALIGN_INT32_T ALIGN_OF(int32_t) -#define ALIGN_INT64_T ALIGN_OF(int64_t) - -extern VALUE mFiddle; -extern VALUE rb_eFiddleDLError; - -VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type); - -typedef void (*rb_fiddle_freefunc_t)(void*); -VALUE rb_fiddle_ptr_new_wrap(void *ptr, long size, rb_fiddle_freefunc_t func, VALUE wrap0, VALUE wrap1); - -enum { - FIDDLE_DEFAULT_TYPED_DATA_FLAGS = ( - RUBY_TYPED_FREE_IMMEDIATELY | - RUBY_TYPED_WB_PROTECTED | -#ifdef RUBY_TYPED_FROZEN_SHAREABLE - RUBY_TYPED_FROZEN_SHAREABLE | -#endif - 0) -}; - -#endif diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c deleted file mode 100644 index 3f574034f4..0000000000 --- a/ext/fiddle/function.c +++ /dev/null @@ -1,500 +0,0 @@ -#include <fiddle.h> -#include <ruby/thread.h> - -#include <stdbool.h> - -#ifdef PRIsVALUE -# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) -# define RB_OBJ_STRING(obj) (obj) -#else -# define PRIsVALUE "s" -# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj) -# define RB_OBJ_STRING(obj) StringValueCStr(obj) -#endif - -VALUE cFiddleFunction; - -#define MAX_ARGS (SIZE_MAX / (sizeof(void *) + sizeof(fiddle_generic)) - 1) - -#define Check_Max_Args(name, len) \ - Check_Max_Args_(name, len, "") -#define Check_Max_Args_Long(name, len) \ - Check_Max_Args_(name, len, "l") -#define Check_Max_Args_(name, len, fmt) \ - do { \ - if ((size_t)(len) >= MAX_ARGS) { \ - rb_raise(rb_eTypeError, \ - "%s is so large " \ - "that it can cause integer overflow (%"fmt"d)", \ - (name), (len)); \ - } \ - } while (0) - -static void -deallocate(void *p) -{ - ffi_cif *cif = p; - if (cif->arg_types) xfree(cif->arg_types); - xfree(cif); -} - -static size_t -function_memsize(const void *p) -{ - /* const */ffi_cif *ptr = (ffi_cif *)p; - size_t size = 0; - - size += sizeof(*ptr); -#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API - size += ffi_raw_size(ptr); -#endif - - return size; -} - -const rb_data_type_t function_data_type = { - .wrap_struct_name = "fiddle/function", - .function = { - .dmark = 0, - .dfree = deallocate, - .dsize = function_memsize - }, - .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, -}; - -static VALUE -allocate(VALUE klass) -{ - ffi_cif * cif; - - return TypedData_Make_Struct(klass, ffi_cif, &function_data_type, cif); -} - -VALUE -rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type) -{ - VALUE argv[3]; - - argv[0] = address; - argv[1] = arg_types; - argv[2] = ret_type; - - return rb_class_new_instance(3, argv, cFiddleFunction); -} - -static VALUE -normalize_argument_types(const char *name, - VALUE arg_types, - bool *is_variadic) -{ - VALUE normalized_arg_types; - int i; - int n_arg_types; - *is_variadic = false; - - Check_Type(arg_types, T_ARRAY); - n_arg_types = RARRAY_LENINT(arg_types); - Check_Max_Args(name, n_arg_types); - - normalized_arg_types = rb_ary_new_capa(n_arg_types); - for (i = 0; i < n_arg_types; i++) { - VALUE arg_type = RARRAY_AREF(arg_types, i); - int c_arg_type; - arg_type = rb_fiddle_type_ensure(arg_type); - c_arg_type = NUM2INT(arg_type); - if (c_arg_type == TYPE_VARIADIC) { - if (i != n_arg_types - 1) { - rb_raise(rb_eArgError, - "Fiddle::TYPE_VARIADIC must be the last argument type: " - "%"PRIsVALUE, - arg_types); - } - *is_variadic = true; - break; - } - else { - (void)INT2FFI_TYPE(c_arg_type); /* raise */ - } - rb_ary_push(normalized_arg_types, INT2FIX(c_arg_type)); - } - - /* freeze to prevent inconsistency at calling #to_int later */ - OBJ_FREEZE(normalized_arg_types); - return normalized_arg_types; -} - -static VALUE -initialize(int argc, VALUE argv[], VALUE self) -{ - ffi_cif * cif; - VALUE ptr, arg_types, ret_type, abi, kwargs; - VALUE name = Qnil; - VALUE need_gvl = Qfalse; - int c_ret_type; - bool is_variadic = false; - ffi_abi c_ffi_abi; - void *cfunc; - - rb_scan_args(argc, argv, "31:", &ptr, &arg_types, &ret_type, &abi, &kwargs); - rb_iv_set(self, "@closure", ptr); - - if (!NIL_P(kwargs)) { - enum { - kw_name, - kw_need_gvl, - kw_max_, - }; - static ID kw[kw_max_]; - VALUE args[kw_max_]; - if (!kw[0]) { - kw[kw_name] = rb_intern_const("name"); - kw[kw_need_gvl] = rb_intern_const("need_gvl"); - } - rb_get_kwargs(kwargs, kw, 0, kw_max_, args); - if (args[kw_name] != Qundef) { - name = args[kw_name]; -#ifdef HAVE_RB_STR_TO_INTERNED_STR - if (RB_TYPE_P(name, RUBY_T_STRING)) { - name = rb_str_to_interned_str(name); - } -#endif - } - if (args[kw_need_gvl] != Qundef) { - need_gvl = args[kw_need_gvl]; - } - } - rb_iv_set(self, "@name", name); - rb_iv_set(self, "@need_gvl", need_gvl); - - ptr = rb_Integer(ptr); - cfunc = NUM2PTR(ptr); - PTR2NUM(cfunc); - c_ffi_abi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi); - abi = INT2FIX(c_ffi_abi); - ret_type = rb_fiddle_type_ensure(ret_type); - c_ret_type = NUM2INT(ret_type); - (void)INT2FFI_TYPE(c_ret_type); /* raise */ - ret_type = INT2FIX(c_ret_type); - - arg_types = normalize_argument_types("argument types", - arg_types, - &is_variadic); -#ifndef HAVE_FFI_PREP_CIF_VAR - if (is_variadic) { - rb_raise(rb_eNotImpError, - "ffi_prep_cif_var() is required in libffi " - "for variadic arguments"); - } -#endif - - rb_iv_set(self, "@ptr", ptr); - rb_iv_set(self, "@argument_types", arg_types); - rb_iv_set(self, "@return_type", ret_type); - rb_iv_set(self, "@abi", abi); - rb_iv_set(self, "@is_variadic", is_variadic ? Qtrue : Qfalse); - - TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif); - cif->arg_types = NULL; - - return self; -} - -struct nogvl_ffi_call_args { - ffi_cif *cif; - void (*fn)(void); - void **values; - fiddle_generic retval; -}; - -static void * -nogvl_ffi_call(void *ptr) -{ - struct nogvl_ffi_call_args *args = ptr; - - ffi_call(args->cif, args->fn, &args->retval, args->values); - - return NULL; -} - -static VALUE -function_call(int argc, VALUE argv[], VALUE self) -{ - struct nogvl_ffi_call_args args = { 0 }; - fiddle_generic *generic_args; - VALUE cfunc; - VALUE abi; - VALUE arg_types; - VALUE cPointer; - VALUE is_variadic; - VALUE need_gvl; - int n_arg_types; - int n_fixed_args = 0; - int n_call_args = 0; - int i; - int i_call; - VALUE converted_args = Qnil; - VALUE alloc_buffer = 0; - - cfunc = rb_iv_get(self, "@ptr"); - abi = rb_iv_get(self, "@abi"); - arg_types = rb_iv_get(self, "@argument_types"); - cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - is_variadic = rb_iv_get(self, "@is_variadic"); - need_gvl = rb_iv_get(self, "@need_gvl"); - - n_arg_types = RARRAY_LENINT(arg_types); - n_fixed_args = n_arg_types; - if (RTEST(is_variadic)) { - if (argc < n_arg_types) { - rb_error_arity(argc, n_arg_types, UNLIMITED_ARGUMENTS); - } - if (((argc - n_arg_types) % 2) != 0) { - rb_raise(rb_eArgError, - "variadic arguments must be type and value pairs: " - "%"PRIsVALUE, - rb_ary_new_from_values(argc, argv)); - } - n_call_args = n_arg_types + ((argc - n_arg_types) / 2); - } - else { - if (argc != n_arg_types) { - rb_error_arity(argc, n_arg_types, n_arg_types); - } - n_call_args = n_arg_types; - } - Check_Max_Args("the number of arguments", n_call_args); - - TypedData_Get_Struct(self, ffi_cif, &function_data_type, args.cif); - - if (is_variadic && args.cif->arg_types) { - xfree(args.cif->arg_types); - args.cif->arg_types = NULL; - } - - if (!args.cif->arg_types) { - VALUE fixed_arg_types = arg_types; - VALUE return_type; - int c_return_type; - ffi_type *ffi_return_type; - ffi_type **ffi_arg_types; - ffi_status result; - - arg_types = rb_ary_dup(fixed_arg_types); - for (i = n_fixed_args; i < argc; i += 2) { - VALUE arg_type = argv[i]; - int c_arg_type; - arg_type = rb_fiddle_type_ensure(arg_type); - c_arg_type = NUM2INT(arg_type); - (void)INT2FFI_TYPE(c_arg_type); /* raise */ - rb_ary_push(arg_types, INT2FIX(c_arg_type)); - } - - return_type = rb_iv_get(self, "@return_type"); - c_return_type = FIX2INT(return_type); - ffi_return_type = INT2FFI_TYPE(c_return_type); - - ffi_arg_types = xcalloc(n_call_args + 1, sizeof(ffi_type *)); - for (i_call = 0; i_call < n_call_args; i_call++) { - VALUE arg_type; - int c_arg_type; - arg_type = RARRAY_AREF(arg_types, i_call); - c_arg_type = FIX2INT(arg_type); - ffi_arg_types[i_call] = INT2FFI_TYPE(c_arg_type); - } - ffi_arg_types[i_call] = NULL; - - if (is_variadic) { -#ifdef HAVE_FFI_PREP_CIF_VAR - result = ffi_prep_cif_var(args.cif, - FIX2INT(abi), - n_fixed_args, - n_call_args, - ffi_return_type, - ffi_arg_types); -#else - /* This code is never used because ffi_prep_cif_var() - * availability check is done in #initialize. */ - result = FFI_BAD_TYPEDEF; -#endif - } - else { - result = ffi_prep_cif(args.cif, - FIX2INT(abi), - n_call_args, - ffi_return_type, - ffi_arg_types); - } - if (result != FFI_OK) { - xfree(ffi_arg_types); - args.cif->arg_types = NULL; - rb_raise(rb_eRuntimeError, "error creating CIF %d", result); - } - } - - generic_args = ALLOCV(alloc_buffer, - sizeof(fiddle_generic) * n_call_args + - sizeof(void *) * (n_call_args + 1)); - args.values = (void **)((char *)generic_args + - sizeof(fiddle_generic) * n_call_args); - - for (i = 0, i_call = 0; - i < argc && i_call < n_call_args; - i++, i_call++) { - VALUE arg_type; - int c_arg_type; - VALUE original_src; - VALUE src; - arg_type = RARRAY_AREF(arg_types, i_call); - c_arg_type = FIX2INT(arg_type); - if (i >= n_fixed_args) { - i++; - } - src = argv[i]; - - if (c_arg_type == TYPE_VOIDP) { - if (NIL_P(src)) { - src = INT2FIX(0); - } - else if (cPointer != CLASS_OF(src)) { - src = rb_funcall(cPointer, rb_intern("[]"), 1, src); - if (NIL_P(converted_args)) { - converted_args = rb_ary_new(); - } - rb_ary_push(converted_args, src); - } - src = rb_Integer(src); - } - - original_src = src; - VALUE2GENERIC(c_arg_type, src, &generic_args[i_call]); - if (src != original_src) { - if (NIL_P(converted_args)) { - converted_args = rb_ary_new(); - } - rb_ary_push(converted_args, src); - } - args.values[i_call] = (void *)&generic_args[i_call]; - } - args.values[i_call] = NULL; - args.fn = (void(*)(void))(VALUE)NUM2PTR(cfunc); - - if (RTEST(need_gvl)) { - ffi_call(args.cif, args.fn, &(args.retval), args.values); - } - else { - (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0); - } - - { - int errno_keep = errno; -#if defined(_WIN32) - DWORD error = WSAGetLastError(); - int socket_error = WSAGetLastError(); - rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, - ULONG2NUM(error)); - rb_funcall(mFiddle, rb_intern("win32_last_socket_error="), 1, - INT2NUM(socket_error)); -#endif - rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno_keep)); - } - - ALLOCV_END(alloc_buffer); - - return GENERIC2VALUE(rb_iv_get(self, "@return_type"), args.retval); -} - -void -Init_fiddle_function(void) -{ - /* - * Document-class: Fiddle::Function - * - * == Description - * - * A representation of a C function - * - * == Examples - * - * === 'strcpy' - * - * @libc = Fiddle.dlopen "/lib/libc.so.6" - * #=> #<Fiddle::Handle:0x00000001d7a8d8> - * f = Fiddle::Function.new( - * @libc['strcpy'], - * [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], - * Fiddle::TYPE_VOIDP) - * #=> #<Fiddle::Function:0x00000001d8ee00> - * buff = "000" - * #=> "000" - * str = f.call(buff, "123") - * #=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000> - * str.to_s - * => "123" - * - * === ABI check - * - * @libc = Fiddle.dlopen "/lib/libc.so.6" - * #=> #<Fiddle::Handle:0x00000001d7a8d8> - * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - * #=> #<Fiddle::Function:0x00000001d8ee00> - * f.abi == Fiddle::Function::DEFAULT - * #=> true - */ - cFiddleFunction = rb_define_class_under(mFiddle, "Function", rb_cObject); - - /* - * Document-const: DEFAULT - * - * Default ABI - * - */ - rb_define_const(cFiddleFunction, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI)); - -#ifdef HAVE_CONST_FFI_STDCALL - /* - * Document-const: STDCALL - * - * FFI implementation of WIN32 stdcall convention - * - */ - rb_define_const(cFiddleFunction, "STDCALL", INT2NUM(FFI_STDCALL)); -#endif - - rb_define_alloc_func(cFiddleFunction, allocate); - - /* - * Document-method: call - * - * Calls the constructed Function, with +args+. - * Caller must ensure the underlying function is called in a - * thread-safe manner if running in a multi-threaded process. - * - * Note that it is not thread-safe to use this method to - * directly or indirectly call many Ruby C-extension APIs unless - * you don't pass +need_gvl: true+ to Fiddle::Function#new. - * - * For an example see Fiddle::Function - * - */ - rb_define_method(cFiddleFunction, "call", function_call, -1); - - /* - * Document-method: new - * call-seq: new(ptr, - * args, - * ret_type, - * abi = DEFAULT, - * name: nil, - * need_gvl: false) - * - * Constructs a Function object. - * * +ptr+ is a referenced function, of a Fiddle::Handle - * * +args+ is an Array of arguments, passed to the +ptr+ function - * * +ret_type+ is the return type of the function - * * +abi+ is the ABI of the function - * * +name+ is the name of the function - * * +need_gvl+ is whether GVL is needed to call the function - * - */ - rb_define_method(cFiddleFunction, "initialize", initialize, -1); -} diff --git a/ext/fiddle/function.h b/ext/fiddle/function.h deleted file mode 100644 index 829e592c8a..0000000000 --- a/ext/fiddle/function.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FIDDLE_FUNCTION_H -#define FIDDLE_FUNCTION_H - -#include <fiddle.h> - -void Init_fiddle_function(void); - -#endif diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c deleted file mode 100644 index 0d03133cab..0000000000 --- a/ext/fiddle/handle.c +++ /dev/null @@ -1,590 +0,0 @@ -#include <ruby.h> -#include <fiddle.h> - -VALUE rb_cHandle; - -struct dl_handle { - void *ptr; - int open; - int enable_close; -}; - -#ifdef _WIN32 -# ifndef _WIN32_WCE -static void * -w32_coredll(void) -{ - MEMORY_BASIC_INFORMATION m; - memset(&m, 0, sizeof(m)); - if( !VirtualQuery(_errno, &m, sizeof(m)) ) return NULL; - return m.AllocationBase; -} -# endif - -static int -w32_dlclose(void *ptr) -{ -# ifndef _WIN32_WCE - if( ptr == w32_coredll() ) return 0; -# endif - if( FreeLibrary((HMODULE)ptr) ) return 0; - return errno = rb_w32_map_errno(GetLastError()); -} -#define dlclose(ptr) w32_dlclose(ptr) -#endif - -static void -fiddle_handle_free(void *ptr) -{ - struct dl_handle *fiddle_handle = ptr; - if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){ - dlclose(fiddle_handle->ptr); - } - xfree(ptr); -} - -static size_t -fiddle_handle_memsize(const void *ptr) -{ - return sizeof(struct dl_handle); -} - -static const rb_data_type_t fiddle_handle_data_type = { - .wrap_struct_name = "fiddle/handle", - .function = { - .dmark = 0, - .dfree = fiddle_handle_free, - .dsize = fiddle_handle_memsize - }, - .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS & ~RUBY_TYPED_FREE_IMMEDIATELY, - /* keeping while its symbols are referred. */ -}; - -/* - * call-seq: close - * - * Close this handle. - * - * Calling close more than once will raise a Fiddle::DLError exception. - */ -static VALUE -rb_fiddle_handle_close(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if(fiddle_handle->open) { - int ret = dlclose(fiddle_handle->ptr); - fiddle_handle->open = 0; - - /* Check dlclose for successful return value */ - if(ret) { -#if defined(HAVE_DLERROR) - rb_raise(rb_eFiddleDLError, "%s", dlerror()); -#else - rb_raise(rb_eFiddleDLError, "could not close handle"); -#endif - } - return INT2NUM(ret); - } - rb_raise(rb_eFiddleDLError, "dlclose() called too many times"); - - UNREACHABLE; -} - -static VALUE -rb_fiddle_handle_s_allocate(VALUE klass) -{ - VALUE obj; - struct dl_handle *fiddle_handle; - - obj = TypedData_Make_Struct(rb_cHandle, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - fiddle_handle->ptr = 0; - fiddle_handle->open = 0; - fiddle_handle->enable_close = 0; - - return obj; -} - -static VALUE -predefined_fiddle_handle(void *handle) -{ - VALUE obj = rb_fiddle_handle_s_allocate(rb_cHandle); - struct dl_handle *fiddle_handle = DATA_PTR(obj); - - fiddle_handle->ptr = handle; - fiddle_handle->open = 1; - OBJ_FREEZE(obj); - return obj; -} - -/* - * call-seq: - * new(library = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL) - * - * Create a new handler that opens +library+ with +flags+. - * - * If no +library+ is specified or +nil+ is given, DEFAULT is used, which is - * the equivalent to RTLD_DEFAULT. See <code>man 3 dlopen</code> for more. - * - * lib = Fiddle::Handle.new - * - * The default is dependent on OS, and provide a handle for all libraries - * already loaded. For example, in most cases you can use this to access +libc+ - * functions, or ruby functions like +rb_str_new+. - */ -static VALUE -rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self) -{ - void *ptr; - struct dl_handle *fiddle_handle; - VALUE lib, flag; - char *clib; - int cflag; - const char *err; - - switch( rb_scan_args(argc, argv, "02", &lib, &flag) ){ - case 0: - clib = NULL; - cflag = RTLD_LAZY | RTLD_GLOBAL; - break; - case 1: - clib = NIL_P(lib) ? NULL : StringValueCStr(lib); - cflag = RTLD_LAZY | RTLD_GLOBAL; - break; - case 2: - clib = NIL_P(lib) ? NULL : StringValueCStr(lib); - cflag = NUM2INT(flag); - break; - default: - rb_bug("rb_fiddle_handle_new"); - } - -#if defined(_WIN32) - if( !clib ){ - HANDLE rb_libruby_handle(void); - ptr = rb_libruby_handle(); - } - else if( STRCASECMP(clib, "libc") == 0 -# ifdef RUBY_COREDLL - || STRCASECMP(clib, RUBY_COREDLL) == 0 - || STRCASECMP(clib, RUBY_COREDLL".dll") == 0 -# endif - ){ -# ifdef _WIN32_WCE - ptr = dlopen("coredll.dll", cflag); -# else - (void)cflag; - ptr = w32_coredll(); -# endif - } - else -#endif - ptr = dlopen(clib, cflag); -#if defined(HAVE_DLERROR) - if( !ptr && (err = dlerror()) ){ - rb_raise(rb_eFiddleDLError, "%s", err); - } -#else - if( !ptr ){ - err = dlerror(); - rb_raise(rb_eFiddleDLError, "%s", err); - } -#endif - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){ - dlclose(fiddle_handle->ptr); - } - fiddle_handle->ptr = ptr; - fiddle_handle->open = 1; - fiddle_handle->enable_close = 0; - - if( rb_block_given_p() ){ - rb_ensure(rb_yield, self, rb_fiddle_handle_close, self); - } - - return Qnil; -} - -/* - * call-seq: enable_close - * - * Enable a call to dlclose() when this handle is garbage collected. - */ -static VALUE -rb_fiddle_handle_enable_close(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - fiddle_handle->enable_close = 1; - return Qnil; -} - -/* - * call-seq: disable_close - * - * Disable a call to dlclose() when this handle is garbage collected. - */ -static VALUE -rb_fiddle_handle_disable_close(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - fiddle_handle->enable_close = 0; - return Qnil; -} - -/* - * call-seq: close_enabled? - * - * Returns +true+ if dlclose() will be called when this handle is garbage collected. - * - * See man(3) dlclose() for more info. - */ -static VALUE -rb_fiddle_handle_close_enabled_p(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - - if(fiddle_handle->enable_close) return Qtrue; - return Qfalse; -} - -/* - * call-seq: to_i - * - * Returns the memory address for this handle. - */ -static VALUE -rb_fiddle_handle_to_i(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - return PTR2NUM(fiddle_handle->ptr); -} - -/* - * call-seq: to_ptr - * - * Returns the Fiddle::Pointer of this handle. - */ -static VALUE -rb_fiddle_handle_to_ptr(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - return rb_fiddle_ptr_new_wrap(fiddle_handle->ptr, 0, 0, self, 0); -} - -static VALUE fiddle_handle_sym(void *handle, VALUE symbol); - -/* - * Document-method: sym - * - * call-seq: sym(name) - * - * Get the address as an Integer for the function named +name+. - */ -static VALUE -rb_fiddle_handle_sym(VALUE self, VALUE sym) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if( ! fiddle_handle->open ){ - rb_raise(rb_eFiddleDLError, "closed handle"); - } - - return fiddle_handle_sym(fiddle_handle->ptr, sym); -} - -#ifndef RTLD_NEXT -#define RTLD_NEXT NULL -#endif -#ifndef RTLD_DEFAULT -#define RTLD_DEFAULT NULL -#endif - -/* - * Document-method: sym - * - * call-seq: sym(name) - * - * Get the address as an Integer for the function named +name+. The function - * is searched via dlsym on RTLD_NEXT. - * - * See man(3) dlsym() for more info. - */ -static VALUE -rb_fiddle_handle_s_sym(VALUE self, VALUE sym) -{ - return fiddle_handle_sym(RTLD_NEXT, sym); -} - -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; -# define CHECK_DLERROR if ((err = dlerror()) != 0) { func = 0; } -#else -# define CHECK_DLERROR -#endif - fiddle_void_func func; - const char *name = StringValueCStr(symbol); - -#ifdef HAVE_DLERROR - dlerror(); -#endif - func = (fiddle_void_func)(VALUE)dlsym(handle, name); - CHECK_DLERROR; -#if defined(FUNC_STDCALL) - if( !func ){ - int i; - int len = (int)strlen(name); - char *name_n; -#if defined(__CYGWIN__) || defined(_WIN32) || defined(__MINGW32__) - { - char *name_a = (char*)xmalloc(len+2); - strcpy(name_a, name); - name_n = name_a; - name_a[len] = 'A'; - name_a[len+1] = '\0'; - func = dlsym(handle, name_a); - CHECK_DLERROR; - if( func ) goto found; - name_n = xrealloc(name_a, len+6); - } -#else - name_n = (char*)xmalloc(len+6); -#endif - memcpy(name_n, name, len); - name_n[len++] = '@'; - for( i = 0; i < 256; i += 4 ){ - sprintf(name_n + len, "%d", i); - func = dlsym(handle, name_n); - CHECK_DLERROR; - if( func ) break; - } - if( func ) goto found; - name_n[len-1] = 'A'; - name_n[len++] = '@'; - for( i = 0; i < 256; i += 4 ){ - sprintf(name_n + len, "%d", i); - func = dlsym(handle, name_n); - CHECK_DLERROR; - if( func ) break; - } - found: - 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); - } - - return PTR2NUM(func); -} - -/* - * call-seq: file_name - * - * Returns the file name of this handle. - */ -static VALUE -rb_fiddle_handle_file_name(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - -#if defined(HAVE_DLINFO) && defined(HAVE_CONST_RTLD_DI_LINKMAP) - { - struct link_map *lm = NULL; - int res = dlinfo(fiddle_handle->ptr, RTLD_DI_LINKMAP, &lm); - if (res == 0 && lm != NULL) { - return rb_str_new_cstr(lm->l_name); - } - else { -#if defined(HAVE_DLERROR) - rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror()); -#else - rb_raise(rb_eFiddleDLError, "could not get handle file name"); -#endif - } - } -#elif defined(HAVE_GETMODULEFILENAME) - { - char filename[MAX_PATH]; - DWORD res = GetModuleFileName(fiddle_handle->ptr, filename, MAX_PATH); - if (res == 0) { - rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror()); - } - return rb_str_new_cstr(filename); - } -#else - (void)fiddle_handle; - return Qnil; -#endif -} - -void -Init_fiddle_handle(void) -{ - /* - * Document-class: Fiddle::Handle - * - * The Fiddle::Handle is the manner to access the dynamic library - * - * == Example - * - * === Setup - * - * libc_so = "/lib64/libc.so.6" - * => "/lib64/libc.so.6" - * @handle = Fiddle::Handle.new(libc_so) - * => #<Fiddle::Handle:0x00000000d69ef8> - * - * === Setup, with flags - * - * libc_so = "/lib64/libc.so.6" - * => "/lib64/libc.so.6" - * @handle = Fiddle::Handle.new(libc_so, Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL) - * => #<Fiddle::Handle:0x00000000d69ef8> - * - * See RTLD_LAZY and RTLD_GLOBAL - * - * === Addresses to symbols - * - * strcpy_addr = @handle['strcpy'] - * => 140062278451968 - * - * or - * - * strcpy_addr = @handle.sym('strcpy') - * => 140062278451968 - * - */ - 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 - * - * A predefined pseudo-handle of RTLD_NEXT - * - * Which will find the next occurrence of a function in the search order - * after the current library. - */ - rb_define_const(rb_cHandle, "NEXT", predefined_fiddle_handle(RTLD_NEXT)); - - /* Document-const: DEFAULT - * - * A predefined pseudo-handle of RTLD_DEFAULT - * - * Which will find the first occurrence of the desired symbol using the - * default library search order - */ - rb_define_const(rb_cHandle, "DEFAULT", predefined_fiddle_handle(RTLD_DEFAULT)); - - /* Document-const: RTLD_GLOBAL - * - * rtld Fiddle::Handle flag. - * - * The symbols defined by this library will be made available for symbol - * resolution of subsequently loaded libraries. - */ - rb_define_const(rb_cHandle, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL)); - - /* Document-const: RTLD_LAZY - * - * rtld Fiddle::Handle flag. - * - * Perform lazy binding. Only resolve symbols as the code that references - * them is executed. If the symbol is never referenced, then it is never - * resolved. (Lazy binding is only performed for function references; - * references to variables are always immediately bound when the library - * is loaded.) - */ - rb_define_const(rb_cHandle, "RTLD_LAZY", INT2NUM(RTLD_LAZY)); - - /* Document-const: RTLD_NOW - * - * rtld Fiddle::Handle flag. - * - * If this value is specified or the environment variable LD_BIND_NOW is - * set to a nonempty string, all undefined symbols in the library are - * resolved before Fiddle.dlopen returns. If this cannot be done an error - * is returned. - */ - rb_define_const(rb_cHandle, "RTLD_NOW", INT2NUM(RTLD_NOW)); - - rb_define_method(rb_cHandle, "initialize", rb_fiddle_handle_initialize, -1); - rb_define_method(rb_cHandle, "to_i", rb_fiddle_handle_to_i, 0); - rb_define_method(rb_cHandle, "to_ptr", rb_fiddle_handle_to_ptr, 0); - 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); - rb_define_method(rb_cHandle, "close_enabled?", rb_fiddle_handle_close_enabled_p, 0); -} diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb deleted file mode 100644 index f242de87c6..0000000000 --- a/ext/fiddle/lib/fiddle.rb +++ /dev/null @@ -1,139 +0,0 @@ -# frozen_string_literal: true - -if RUBY_ENGINE == 'ruby' - require 'fiddle.so' -else - require 'fiddle/ffi_backend' -end -require 'fiddle/closure' -require 'fiddle/function' -require 'fiddle/version' - -module Fiddle - if RUBY_ENGINE != 'ruby' # FFI backend - def self.last_error - FFI.errno - end - - def self.last_error=(error) - FFI.errno = error || 0 - end - - if WINDOWS - class << self - def win32_last_error - FFI.errno.nonzero? - end - def win32_last_error=(error) - FFI.errno = error || 0 - end - - def win32_last_socket_error - FFI.errno.nonzero? - end - def win32_last_socket_error=(error) - FFI.errno = error || 0 - end - end - end - else - # Returns the last +Error+ of the current executing +Thread+ or nil if none - def self.last_error - Thread.current[:__FIDDLE_LAST_ERROR__] - end - - # Sets the last +Error+ of the current executing +Thread+ to +error+ - def self.last_error= error - Thread.current[:__DL2_LAST_ERROR__] = error - Thread.current[:__FIDDLE_LAST_ERROR__] = error - end - - if WINDOWS - # Returns the last win32 +Error+ of the current executing +Thread+ or nil - # if none - def self.win32_last_error - Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] - end - - # Sets the last win32 +Error+ of the current executing +Thread+ to +error+ - def self.win32_last_error= error - Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error - end - - # Returns the last win32 socket +Error+ of the current executing - # +Thread+ or nil if none - def self.win32_last_socket_error - Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] - end - - # Sets the last win32 socket +Error+ of the current executing - # +Thread+ to +error+ - def self.win32_last_socket_error= error - Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error - end - end - end - - case RUBY_PLATFORM - when /linux/ - def dlopen library - Fiddle::Handle.new(library) - rescue DLError => error - 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 - - 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? - first_input = $1 - if first_input.start_with?("-l") - first_input = "lib#{first_input[2..-1]}.so" - end - return dlopen(first_input) - end - end - end - - # Not found - raise - end - else - # call-seq: dlopen(library) => Fiddle::Handle - # - # Creates a new handler that opens +library+, and returns an instance of - # Fiddle::Handle. - # - # If +nil+ is given for the +library+, Fiddle::Handle::DEFAULT is used, which - # is the equivalent to RTLD_DEFAULT. See <code>man 3 dlopen</code> for more. - # - # lib = Fiddle.dlopen(nil) - # - # The default is dependent on OS, and provide a handle for all libraries - # already loaded. For example, in most cases you can use this to access - # +libc+ functions, or ruby functions like +rb_str_new+. - # - # See Fiddle::Handle.new for more. - def dlopen library - Fiddle::Handle.new(library) - end - end - module_function :dlopen - - # Add constants for backwards compat - - 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 deleted file mode 100644 index 7e0077ea52..0000000000 --- a/ext/fiddle/lib/fiddle/closure.rb +++ /dev/null @@ -1,74 +0,0 @@ -# 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 - - # arguments of the FFI closure - attr_reader :args - - # Extends Fiddle::Closure to allow for building the closure in a block - class BlockCaller < Fiddle::Closure - - # == Description - # - # Construct a new BlockCaller object. - # - # * +ctype+ is the C type to be returned - # * +args+ are passed the callback - # * +abi+ is the abi of the closure - # - # If there is an error in preparing the +ffi_cif+ or +ffi_prep_closure+, - # then a RuntimeError will be raised. - # - # == Example - # - # include Fiddle - # - # cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one| - # one - # end - # - # func = Function.new(cb, [TYPE_INT], TYPE_INT) - # - def initialize ctype, args, abi = Fiddle::Function::DEFAULT, &block - super(ctype, args, abi) - @block = block - end - - # Calls the constructed BlockCaller, with +args+ - # - # For an example see Fiddle::Closure::BlockCaller.new - # - def call *args - @block.call(*args) - end - end - end -end diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb deleted file mode 100644 index cdd139d515..0000000000 --- a/ext/fiddle/lib/fiddle/cparser.rb +++ /dev/null @@ -1,278 +0,0 @@ -# frozen_string_literal: true -module Fiddle - # A mixin that provides methods for parsing C struct and prototype signatures. - # - # == Example - # require 'fiddle/import' - # - # include Fiddle::CParser - # #=> Object - # - # parse_ctype('int') - # #=> Fiddle::TYPE_INT - # - # parse_struct_signature(['int i', 'char c']) - # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] - # - # parse_signature('double sum(double, double)') - # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] - # - module CParser - # Parses a C struct's members - # - # Example: - # require 'fiddle/import' - # - # include Fiddle::CParser - # #=> Object - # - # parse_struct_signature(['int i', 'char c']) - # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] - # - # parse_struct_signature(['char buffer[80]']) - # #=> [[[Fiddle::TYPE_CHAR, 80]], ["buffer"]] - # - def parse_struct_signature(signature, tymap=nil) - if signature.is_a?(String) - signature = split_arguments(signature, /[,;]/) - elsif signature.is_a?(Hash) - signature = [signature] - end - mems = [] - tys = [] - signature.each{|msig| - msig = compact(msig) if msig.is_a?(String) - case msig - when Hash - msig.each do |struct_name, struct_signature| - struct_name = struct_name.to_s if struct_name.is_a?(Symbol) - struct_name = compact(struct_name) - struct_count = nil - if struct_name =~ /^([\w\*\s]+)\[(\d+)\]$/ - struct_count = $2.to_i - struct_name = $1 - end - if struct_signature.respond_to?(:entity_class) - struct_type = struct_signature - else - parsed_struct = parse_struct_signature(struct_signature, tymap) - struct_type = CStructBuilder.create(CStruct, *parsed_struct) - end - if struct_count - ty = [struct_type, struct_count] - else - ty = struct_type - end - mems.push([struct_name, struct_type.members]) - tys.push(ty) - end - when /^[\w\*\s]+[\*\s](\w+)$/ - mems.push($1) - tys.push(parse_ctype(msig, tymap)) - when /^[\w\*\s]+\(\*(\w+)\)\(.*?\)$/ - mems.push($1) - tys.push(parse_ctype(msig, tymap)) - when /^([\w\*\s]+[\*\s])(\w+)\[(\d+)\]$/ - mems.push($2) - tys.push([parse_ctype($1.strip, tymap), $3.to_i]) - when /^([\w\*\s]+)\[(\d+)\](\w+)$/ - mems.push($3) - tys.push([parse_ctype($1.strip, tymap), $2.to_i]) - else - raise(RuntimeError,"can't parse the struct member: #{msig}") - end - } - return tys, mems - end - - # Parses a C prototype signature - # - # If Hash +tymap+ is provided, the return value and the arguments from the - # +signature+ are expected to be keys, and the value will be the C type to - # be looked up. - # - # Example: - # require 'fiddle/import' - # - # include Fiddle::CParser - # #=> Object - # - # parse_signature('double sum(double, double)') - # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] - # - # parse_signature('void update(void (*cb)(int code))') - # #=> ["update", Fiddle::TYPE_VOID, [Fiddle::TYPE_VOIDP]] - # - # parse_signature('char (*getbuffer(void))[80]') - # #=> ["getbuffer", Fiddle::TYPE_VOIDP, []] - # - def parse_signature(signature, tymap=nil) - tymap ||= {} - case compact(signature) - when /^(?:[\w\*\s]+)\(\*(\w+)\((.*?)\)\)(?:\[\w*\]|\(.*?\));?$/ - func, args = $1, $2 - return [func, TYPE_VOIDP, split_arguments(args).collect {|arg| parse_ctype(arg, tymap)}] - when /^([\w\*\s]+[\*\s])(\w+)\((.*?)\);?$/ - ret, func, args = $1.strip, $2, $3 - return [func, parse_ctype(ret, tymap), split_arguments(args).collect {|arg| parse_ctype(arg, tymap)}] - else - raise(RuntimeError,"can't parse the function prototype: #{signature}") - end - end - - # Given a String of C type +ty+, returns the corresponding Fiddle constant. - # - # +ty+ can also accept an Array of C type Strings, and will be returned in - # a corresponding Array. - # - # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the - # value will be the C type to be looked up. - # - # Example: - # require 'fiddle/import' - # - # include Fiddle::CParser - # #=> Object - # - # parse_ctype('int') - # #=> Fiddle::TYPE_INT - # - # parse_ctype('double diff') - # #=> Fiddle::TYPE_DOUBLE - # - # parse_ctype('unsigned char byte') - # #=> -Fiddle::TYPE_CHAR - # - # parse_ctype('const char* const argv[]') - # #=> -Fiddle::TYPE_VOIDP - # - def parse_ctype(ty, tymap=nil) - tymap ||= {} - if ty.is_a?(Array) - return [parse_ctype(ty[0], tymap), ty[1]] - end - ty = ty.gsub(/\Aconst\s+/, "") - case ty - when 'void' - return TYPE_VOID - when /\A(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_LONG_LONG) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_LONG_LONG - when /\A(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_LONG_LONG) - raise(RuntimeError, "unsupported type: #{ty}") - end - 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+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+)?char(?:\s+\w+)?\z/ - return TYPE_CHAR - when /\Aunsigned\s+char(?:\s+\w+)?\z/ - return TYPE_UCHAR - when /\Aint8_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT8_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_INT8_T - when /\Auint8_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT8_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_UINT8_T - when /\Aint16_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT16_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_INT16_T - when /\Auint16_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT16_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_UINT16_T - when /\Aint32_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT32_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_INT32_T - when /\Auint32_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT32_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_UINT32_T - when /\Aint64_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT64_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_INT64_T - when /\Auint64_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT64_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_UINT64_T - when /\Afloat(?:\s+\w+)?\z/ - return TYPE_FLOAT - when /\Adouble(?:\s+\w+)?\z/ - return TYPE_DOUBLE - when /\Asize_t(?:\s+\w+)?\z/ - return TYPE_SIZE_T - when /\Assize_t(?:\s+\w+)?\z/ - return TYPE_SSIZE_T - when /\Aptrdiff_t(?:\s+\w+)?\z/ - return TYPE_PTRDIFF_T - when /\Aintptr_t(?:\s+\w+)?\z/ - return TYPE_INTPTR_T - when /\Auintptr_t(?:\s+\w+)?\z/ - return TYPE_UINTPTR_T - when /\Abool(?:\s+\w+)?\z/ - return TYPE_BOOL - when /\*/, /\[[\s\d]*\]/ - return TYPE_VOIDP - when "..." - return TYPE_VARIADIC - else - ty = ty.split(' ', 2)[0] - if( tymap[ty] ) - return parse_ctype(tymap[ty], tymap) - else - raise(DLError, "unknown type: #{ty}") - end - end - end - - private - - def split_arguments(arguments, sep=',') - return [] if arguments.strip == 'void' - arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+|\.\.\.)(?:#{sep}\s*|\z)/).collect {|m| m[0]} - end - - def compact(signature) - signature.gsub(/\s+/, ' ').gsub(/\s*([\(\)\[\]\*,;])\s*/, '\1').strip - end - - end -end diff --git a/ext/fiddle/lib/fiddle/ffi_backend.rb b/ext/fiddle/lib/fiddle/ffi_backend.rb deleted file mode 100644 index 5cfceb19a8..0000000000 --- a/ext/fiddle/lib/fiddle/ffi_backend.rb +++ /dev/null @@ -1,627 +0,0 @@ -# This is based on JRuby's FFI-based fiddle implementation. - -require 'ffi' - -module Fiddle - def self.malloc(size) - Fiddle::Pointer.malloc(size) - end - - def self.free(ptr) - Fiddle::Pointer::LibC::FREE.call(ptr) - nil - end - - def self.dlwrap(val) - Pointer.to_ptr(val) - end - - module Types - VOID = 0 - VOIDP = 1 - CHAR = 2 - UCHAR = -CHAR - SHORT = 3 - USHORT = -SHORT - INT = 4 - UINT = -INT - LONG = 5 - ULONG = -LONG - LONG_LONG = 6 - ULONG_LONG = -LONG_LONG - FLOAT = 7 - DOUBLE = 8 - VARIADIC = 9 - CONST_STRING = 10 - BOOL = 11 - INT8_T = CHAR - UINT8_T = UCHAR - if FFI::Type::Builtin::SHORT.size == 2 - INT16_T = SHORT - UINT16_T = USHORT - elsif FFI::Type::Builtin::INT.size == 2 - INT16_T = INT - UINT16_T = UINT - end - if FFI::Type::Builtin::SHORT.size == 4 - INT32_T = SHORT - UINT32_T = USHORT - elsif FFI::Type::Builtin::INT.size == 4 - INT32_T = INT - UINT32_T = UINT - elsif FFI::Type::Builtin::LONG.size == 4 - INT32_T = LONG - UINT32_T = ULONG - end - if FFI::Type::Builtin::INT.size == 8 - INT64_T = INT - UINT64_T = UINT - elsif FFI::Type::Builtin::LONG.size == 8 - INT64_T = LONG - UINT64_T = ULONG - else - INT64_T = LONG_LONG - UINT64_T = ULONG_LONG - end - - # FIXME: platform specific values - SSIZE_T = INT64_T - SIZE_T = -SSIZE_T - PTRDIFF_T = SSIZE_T - INTPTR_T = INT64_T - UINTPTR_T = -INTPTR_T - end - - WINDOWS = FFI::Platform.windows? - - module FFIBackend - FFITypes = { - 'c' => FFI::Type::INT8, - 'h' => FFI::Type::INT16, - 'i' => FFI::Type::INT32, - 'l' => FFI::Type::LONG, - 'f' => FFI::Type::FLOAT32, - 'd' => FFI::Type::FLOAT64, - 'p' => FFI::Type::POINTER, - 's' => FFI::Type::STRING, - - Types::VOID => FFI::Type::Builtin::VOID, - Types::VOIDP => FFI::Type::Builtin::POINTER, - Types::CHAR => FFI::Type::Builtin::CHAR, - Types::UCHAR => FFI::Type::Builtin::UCHAR, - Types::SHORT => FFI::Type::Builtin::SHORT, - Types::USHORT => FFI::Type::Builtin::USHORT, - Types::INT => FFI::Type::Builtin::INT, - Types::UINT => FFI::Type::Builtin::UINT, - Types::LONG => FFI::Type::Builtin::LONG, - Types::ULONG => FFI::Type::Builtin::ULONG, - Types::LONG_LONG => FFI::Type::Builtin::LONG_LONG, - Types::ULONG_LONG => FFI::Type::Builtin::ULONG_LONG, - Types::FLOAT => FFI::Type::Builtin::FLOAT, - Types::DOUBLE => FFI::Type::Builtin::DOUBLE, - Types::BOOL => FFI::Type::Builtin::BOOL, - Types::CONST_STRING => FFI::Type::Builtin::POINTER, - Types::VARIADIC => FFI::Type::Builtin::VARARGS, - } - - def self.to_ffi_type(fiddle_type) - if fiddle_type.is_a?(Symbol) - fiddle_type = Types.const_get(fiddle_type.to_s.upcase) - end - if !fiddle_type.is_a?(Integer) && fiddle_type.respond_to?(:to_int) - fiddle_type = fiddle_type.to_int - end - ffi_type = FFITypes[fiddle_type] - ffi_type = FFITypes[-fiddle_type] if ffi_type.nil? && fiddle_type.is_a?(Integer) && fiddle_type < 0 - raise TypeError.new("cannot convert #{fiddle_type} to ffi") unless ffi_type - ffi_type - end - end - - class Function - DEFAULT = "default" - STDCALL = "stdcall" - - def initialize(ptr, args, return_type, abi = DEFAULT, kwargs = nil) - if kwargs.nil? - if abi.kind_of? Hash - kwargs = abi - abi = DEFAULT - end - end - @name = kwargs[:name] if kwargs.kind_of? Hash - @ptr, @args, @return_type, @abi = ptr, args, return_type, abi - raise TypeError.new "invalid argument types" unless args.is_a?(Array) - - ffi_return_type = Fiddle::FFIBackend.to_ffi_type(@return_type) - ffi_args = @args.map { |t| Fiddle::FFIBackend.to_ffi_type(t) } - pointer = FFI::Pointer.new(ptr.to_i) - options = {convention: @abi} - if ffi_args.last == FFI::Type::Builtin::VARARGS - @function = FFI::VariadicInvoker.new( - pointer, - ffi_args, - ffi_return_type, - options - ) - else - @function = FFI::Function.new(ffi_return_type, ffi_args, pointer, options) - end - end - - def call(*args, &block) - if @function.is_a?(FFI::VariadicInvoker) - n_fixed_args = @args.size - 1 - n_fixed_args.step(args.size - 1, 2) do |i| - if args[i] == :const_string || args[i] == Types::CONST_STRING - args[i + 1] = String.try_convert(args[i + 1]) || args[i + 1] - end - args[i] = Fiddle::FFIBackend.to_ffi_type(args[i]) - end - else - @args.each_with_index do |arg_type, i| - next unless arg_type == Types::VOIDP - - src = args[i] - next if src.nil? - next if src.is_a?(String) - next if src.is_a?(FFI::AbstractMemory) - next if src.is_a?(FFI::Struct) - - args[i] = Pointer[src] - end - end - result = @function.call(*args, &block) - result = Pointer.new(result) if result.is_a?(FFI::Pointer) - result - end - end - - class Closure - def initialize(ret, args, abi = Function::DEFAULT) - raise TypeError.new "invalid argument types" unless args.is_a?(Array) - - @ctype, @args = ret, args - ffi_args = @args.map { |t| Fiddle::FFIBackend.to_ffi_type(t) } - if ffi_args.size == 1 && ffi_args[0] == FFI::Type::Builtin::VOID - ffi_args = [] - end - return_type = Fiddle::FFIBackend.to_ffi_type(@ctype) - raise "#{self.class} must implement #call" unless respond_to?(:call) - callable = method(:call) - @function = FFI::Function.new(return_type, ffi_args, callable, convention: abi) - @freed = false - end - - def to_ptr - @function - end - - def to_i - @function.to_i - end - - def free - return if @freed - @function.free - @freed = true - end - - def freed? - @freed - end - end - - class Error < StandardError; end - class DLError < Error; end - class ClearedReferenceError < Error; end - - class Pointer - attr_reader :ffi_ptr - extend FFI::DataConverter - native_type FFI::Type::Builtin::POINTER - - def self.to_native(value, ctx) - if value.is_a?(Pointer) - value.ffi_ptr - - elsif value.is_a?(Integer) - FFI::Pointer.new(value) - - elsif value.is_a?(String) - value - end - end - - def self.from_native(value, ctx) - self.new(value) - end - - def self.to_ptr(value) - if value.is_a?(String) - cptr = Pointer.malloc(value.bytesize) - cptr.ffi_ptr.put_string(0, value) - cptr - - elsif value.is_a?(Array) - raise NotImplementedError, "array ptr" - - elsif value.respond_to?(:to_ptr) - ptr = value.to_ptr - case ptr - when Pointer - ptr - when FFI::Pointer - Pointer.new(ptr) - else - raise DLError.new("to_ptr should return a Fiddle::Pointer object, was #{ptr.class}") - end - - else - Pointer.new(value) - end - end - - def self.write(addr, bytes) - FFI::Pointer.new(addr).write_bytes(bytes) - end - - def self.read(addr, len) - FFI::Pointer.new(addr).read_bytes(len) - end - - class << self - alias [] to_ptr - end - - def []=(*args, value) - if args.size == 2 - if value.is_a?(Integer) - value = self.class.new(value) - end - if value.is_a?(Fiddle::Pointer) - value = value.to_str(args[1]) - end - - @ffi_ptr.put_bytes(args[0], value, 0, args[1]) - elsif args.size == 1 - if value.is_a?(Fiddle::Pointer) - value = value.to_str(args[0] + 1) - else - value = value.chr - end - - @ffi_ptr.put_bytes(args[0], value, 0, 1) - end - rescue FFI::NullPointerError - raise DLError.new("NULL pointer access") - end - - def initialize(addr, size = nil, free = nil) - ptr = if addr.is_a?(FFI::Pointer) - addr - - elsif addr.is_a?(Integer) - FFI::Pointer.new(addr) - - elsif addr.respond_to?(:to_ptr) - fiddle_ptr = addr.to_ptr - if fiddle_ptr.is_a?(Pointer) - fiddle_ptr.ffi_ptr - elsif fiddle_ptr.is_a?(FFI::AutoPointer) - addr.ffi_ptr - elsif fiddle_ptr.is_a?(FFI::Pointer) - fiddle_ptr - else - raise DLError.new("to_ptr should return a Fiddle::Pointer object, was #{fiddle_ptr.class}") - end - elsif addr.is_a?(IO) - raise NotImplementedError, "IO ptr isn't supported" - else - FFI::Pointer.new(Integer(addr)) - end - - @size = size ? size : ptr.size - @free = free - @ffi_ptr = ptr - @freed = false - end - - module LibC - extend FFI::Library - ffi_lib FFI::Library::LIBC - MALLOC = attach_function :malloc, [ :size_t ], :pointer - REALLOC = attach_function :realloc, [ :pointer, :size_t ], :pointer - FREE = attach_function :free, [ :pointer ], :void - end - - def self.malloc(size, free = nil) - if block_given? and free.nil? - message = "a free function must be supplied to #{self}.malloc " + - "when it is called with a block" - raise ArgumentError, message - end - - pointer = new(LibC.malloc(size), size, free) - if block_given? - begin - yield(pointer) - ensure - pointer.call_free - end - else - pointer - end - end - - def null? - @ffi_ptr.null? - end - - def to_ptr - @ffi_ptr - end - - def size - defined?(@layout) ? @layout.size : @size - end - - def free - @free - end - - def free=(free) - @free = free - end - - def call_free - return if @free.nil? - return if @freed - if @free == RUBY_FREE - LibC::FREE.call(@ffi_ptr) - else - @free.call(@ffi_ptr) - end - @freed = true - end - - def freed? - @freed - end - - def size=(size) - @size = size - end - - def [](index, length = nil) - if length - ffi_ptr.get_bytes(index, length) - else - ffi_ptr.get_char(index) - end - rescue FFI::NullPointerError - raise DLError.new("NULL pointer dereference") - end - - def to_i - ffi_ptr.to_i - end - alias to_int to_i - - # without \0 - def to_s(len = nil) - if len - ffi_ptr.get_string(0, len) - else - ffi_ptr.get_string(0) - end - rescue FFI::NullPointerError - raise DLError.new("NULL pointer access") - end - - def to_str(len = nil) - if len - ffi_ptr.read_string(len) - else - ffi_ptr.read_string(@size) - end - rescue FFI::NullPointerError - raise DLError.new("NULL pointer access") - end - - def to_value - raise NotImplementedError, "to_value isn't supported" - end - - def inspect - "#<#{self.class.name} ptr=#{to_i.to_s(16)} size=#{@size} free=#{@free.inspect}>" - end - - def +(delta) - self.class.new(to_i + delta, @size - delta) - end - - def -(delta) - self.class.new(to_i - delta, @size + delta) - end - - def <=>(other) - return unless other.is_a?(Pointer) - diff = self.to_i - other.to_i - return 0 if diff == 0 - diff > 0 ? 1 : -1 - end - - def eql?(other) - return unless other.is_a?(Pointer) - self.to_i == other.to_i - end - - def ==(other) - eql?(other) - end - - def ptr - Pointer.new(ffi_ptr.get_pointer(0)) - end - - def +@ - ptr - end - - def -@ - ref - end - - def ref - cptr = Pointer.malloc(FFI::Type::POINTER.size, RUBY_FREE) - cptr.ffi_ptr.put_pointer(0, ffi_ptr) - cptr - end - end - - class Handle - RTLD_GLOBAL = FFI::DynamicLibrary::RTLD_GLOBAL - RTLD_LAZY = FFI::DynamicLibrary::RTLD_LAZY - RTLD_NOW = FFI::DynamicLibrary::RTLD_NOW - - def initialize(libname = nil, flags = RTLD_LAZY | RTLD_GLOBAL) - begin - @lib = FFI::DynamicLibrary.open(libname, flags) - rescue LoadError, RuntimeError # LoadError for JRuby, RuntimeError for TruffleRuby - raise DLError, "Could not open #{libname}" - end - - @open = true - - begin - yield(self) - ensure - self.close - end if block_given? - end - - def close - raise DLError.new("closed handle") unless @open - @open = false - 0 - end - - def self.sym(func) - DEFAULT.sym(func) - end - - def sym(func) - raise TypeError.new("invalid function name") unless func.is_a?(String) - raise DLError.new("closed handle") unless @open - address = @lib.find_function(func) - raise DLError.new("unknown symbol #{func}") if address.nil? || address.null? - address.to_i - end - - def self.sym_defined?(func) - DEFAULT.sym_defined?(func) - end - - def sym_defined?(func) - raise TypeError.new("invalid function name") unless func.is_a?(String) - raise DLError.new("closed handle") unless @open - address = @lib.find_function(func) - !address.nil? && !address.null? - end - - def self.[](func) - self.sym(func) - end - - def [](func) - sym(func) - end - - def enable_close - @enable_close = true - end - - def close_enabled? - @enable_close - end - - def disable_close - @enable_close = false - end - - DEFAULT = new - end - - class Pinned - def initialize(object) - @object = object - end - - def ref - if @object.nil? - raise ClearedReferenceError, "`ref` called on a cleared object" - end - @object - end - - def clear - @object = nil - end - - def cleared? - @object.nil? - end - end - - RUBY_FREE = Fiddle::Pointer::LibC::FREE.address - NULL = Fiddle::Pointer.new(0) - - ALIGN_VOIDP = Fiddle::FFIBackend::FFITypes[Types::VOIDP].alignment - ALIGN_CHAR = Fiddle::FFIBackend::FFITypes[Types::CHAR].alignment - ALIGN_SHORT = Fiddle::FFIBackend::FFITypes[Types::SHORT].alignment - ALIGN_INT = Fiddle::FFIBackend::FFITypes[Types::INT].alignment - ALIGN_LONG = Fiddle::FFIBackend::FFITypes[Types::LONG].alignment - ALIGN_LONG_LONG = Fiddle::FFIBackend::FFITypes[Types::LONG_LONG].alignment - ALIGN_INT8_T = Fiddle::FFIBackend::FFITypes[Types::INT8_T].alignment - ALIGN_INT16_T = Fiddle::FFIBackend::FFITypes[Types::INT16_T].alignment - ALIGN_INT32_T = Fiddle::FFIBackend::FFITypes[Types::INT32_T].alignment - ALIGN_INT64_T = Fiddle::FFIBackend::FFITypes[Types::INT64_T].alignment - ALIGN_FLOAT = Fiddle::FFIBackend::FFITypes[Types::FLOAT].alignment - ALIGN_DOUBLE = Fiddle::FFIBackend::FFITypes[Types::DOUBLE].alignment - ALIGN_BOOL = Fiddle::FFIBackend::FFITypes[Types::BOOL].alignment - ALIGN_SIZE_T = Fiddle::FFIBackend::FFITypes[Types::SIZE_T].alignment - ALIGN_SSIZE_T = ALIGN_SIZE_T - ALIGN_PTRDIFF_T = Fiddle::FFIBackend::FFITypes[Types::PTRDIFF_T].alignment - ALIGN_INTPTR_T = Fiddle::FFIBackend::FFITypes[Types::INTPTR_T].alignment - ALIGN_UINTPTR_T = Fiddle::FFIBackend::FFITypes[Types::UINTPTR_T].alignment - - SIZEOF_VOIDP = Fiddle::FFIBackend::FFITypes[Types::VOIDP].size - SIZEOF_CHAR = Fiddle::FFIBackend::FFITypes[Types::CHAR].size - SIZEOF_UCHAR = Fiddle::FFIBackend::FFITypes[Types::UCHAR].size - SIZEOF_SHORT = Fiddle::FFIBackend::FFITypes[Types::SHORT].size - SIZEOF_USHORT = Fiddle::FFIBackend::FFITypes[Types::USHORT].size - SIZEOF_INT = Fiddle::FFIBackend::FFITypes[Types::INT].size - SIZEOF_UINT = Fiddle::FFIBackend::FFITypes[Types::UINT].size - SIZEOF_LONG = Fiddle::FFIBackend::FFITypes[Types::LONG].size - SIZEOF_ULONG = Fiddle::FFIBackend::FFITypes[Types::ULONG].size - SIZEOF_LONG_LONG = Fiddle::FFIBackend::FFITypes[Types::LONG_LONG].size - SIZEOF_ULONG_LONG = Fiddle::FFIBackend::FFITypes[Types::ULONG_LONG].size - SIZEOF_INT8_T = Fiddle::FFIBackend::FFITypes[Types::INT8_T].size - SIZEOF_UINT8_T = Fiddle::FFIBackend::FFITypes[Types::UINT8_T].size - SIZEOF_INT16_T = Fiddle::FFIBackend::FFITypes[Types::INT16_T].size - SIZEOF_UINT16_T = Fiddle::FFIBackend::FFITypes[Types::UINT16_T].size - SIZEOF_INT32_T = Fiddle::FFIBackend::FFITypes[Types::INT32_T].size - SIZEOF_UINT32_T = Fiddle::FFIBackend::FFITypes[Types::UINT32_T].size - SIZEOF_INT64_T = Fiddle::FFIBackend::FFITypes[Types::INT64_T].size - SIZEOF_UINT64_T = Fiddle::FFIBackend::FFITypes[Types::UINT64_T].size - SIZEOF_FLOAT = Fiddle::FFIBackend::FFITypes[Types::FLOAT].size - SIZEOF_DOUBLE = Fiddle::FFIBackend::FFITypes[Types::DOUBLE].size - SIZEOF_BOOL = Fiddle::FFIBackend::FFITypes[Types::BOOL].size - SIZEOF_SIZE_T = Fiddle::FFIBackend::FFITypes[Types::SIZE_T].size - SIZEOF_SSIZE_T = SIZEOF_SIZE_T - SIZEOF_PTRDIFF_T = Fiddle::FFIBackend::FFITypes[Types::PTRDIFF_T].size - SIZEOF_INTPTR_T = Fiddle::FFIBackend::FFITypes[Types::INTPTR_T].size - SIZEOF_UINTPTR_T = Fiddle::FFIBackend::FFITypes[Types::UINTPTR_T].size - SIZEOF_CONST_STRING = Fiddle::FFIBackend::FFITypes[Types::VOIDP].size -end diff --git a/ext/fiddle/lib/fiddle/function.rb b/ext/fiddle/lib/fiddle/function.rb deleted file mode 100644 index dc2e3e6bf5..0000000000 --- a/ext/fiddle/lib/fiddle/function.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true -module Fiddle - class Function - # The ABI of the Function. - attr_reader :abi - - # The address of this function - attr_reader :ptr - - # The name of this function - attr_reader :name - - # Whether GVL is needed to call this function - def need_gvl? - @need_gvl - end - - # The integer memory location of this function - def to_i - ptr.to_i - end - - # Turn this function in to a proc - def to_proc - this = self - lambda { |*args| this.call(*args) } - end - end -end diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb deleted file mode 100644 index 050708fb96..0000000000 --- a/ext/fiddle/lib/fiddle/import.rb +++ /dev/null @@ -1,322 +0,0 @@ -# frozen_string_literal: true -require 'fiddle' -require 'fiddle/struct' -require 'fiddle/cparser' - -module Fiddle - - # Used internally by Fiddle::Importer - class CompositeHandler - # Create a new handler with the open +handlers+ - # - # Used internally by Fiddle::Importer.dlload - def initialize(handlers) - @handlers = handlers - end - - # Array of the currently loaded libraries. - def handlers() - @handlers - end - - # Returns the address as an Integer from any handlers with the function - # named +symbol+. - # - # Raises a DLError if the handle is closed. - def sym(symbol) - @handlers.each{|handle| - if( handle ) - begin - addr = handle.sym(symbol) - return addr - rescue DLError - end - end - } - return nil - end - - # See Fiddle::CompositeHandler.sym - def [](symbol) - sym(symbol) - end - end - - # A DSL that provides the means to dynamically load libraries and build - # modules around them including calling extern functions within the C - # library that has been loaded. - # - # == Example - # - # require 'fiddle' - # require 'fiddle/import' - # - # module LibSum - # extend Fiddle::Importer - # dlload './libsum.so' - # extern 'double sum(double*, int)' - # extern 'double split(double)' - # end - # - module Importer - include Fiddle - include CParser - extend Importer - - attr_reader :type_alias - private :type_alias - - # Creates an array of handlers for the given +libs+, can be an instance of - # Fiddle::Handle, Fiddle::Importer, or will create a new instance of - # Fiddle::Handle using Fiddle.dlopen - # - # Raises a DLError if the library cannot be loaded. - # - # See Fiddle.dlopen - def dlload(*libs) - handles = libs.collect{|lib| - case lib - when nil - nil - when Handle - lib - when Importer - lib.handlers - else - Fiddle.dlopen(lib) - end - }.flatten() - @handler = CompositeHandler.new(handles) - @func_map = {} - @type_alias = {} - end - - # Sets the type alias for +alias_type+ as +orig_type+ - def typealias(alias_type, orig_type) - @type_alias[alias_type] = orig_type - end - - # Returns the sizeof +ty+, using Fiddle::Importer.parse_ctype to determine - # the C type and the appropriate Fiddle constant. - def sizeof(ty) - case ty - when String - ty = parse_ctype(ty, type_alias).abs() - case ty - when TYPE_CHAR - return SIZEOF_CHAR - when TYPE_SHORT - return SIZEOF_SHORT - when TYPE_INT - return SIZEOF_INT - when TYPE_LONG - return SIZEOF_LONG - when TYPE_FLOAT - return SIZEOF_FLOAT - when TYPE_DOUBLE - return SIZEOF_DOUBLE - when TYPE_VOIDP - 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 - return SIZEOF_LONG_LONG - else - raise(DLError, "unknown type: #{ty}") - end - end - when Class - if( ty.instance_methods().include?(:to_ptr) ) - return ty.size() - end - end - return Pointer[ty].size() - end - - def parse_bind_options(opts) - h = {} - while( opt = opts.shift() ) - case opt - when :stdcall, :cdecl - h[:call_type] = opt - when :carried, :temp, :temporal, :bind - h[:callback_type] = opt - h[:carrier] = opts.shift() - else - h[opt] = true - end - end - h - end - private :parse_bind_options - - # :stopdoc: - CALL_TYPE_TO_ABI = Hash.new { |h, k| - raise RuntimeError, "unsupported call type: #{k}" - }.merge({ :stdcall => Function.const_defined?(:STDCALL) ? Function::STDCALL : - Function::DEFAULT, - :cdecl => Function::DEFAULT, - nil => Function::DEFAULT - }).freeze - private_constant :CALL_TYPE_TO_ABI - # :startdoc: - - # Creates a global method from the given C +signature+. - def extern(signature, *opts) - symname, ctype, argtype = parse_signature(signature, type_alias) - opt = parse_bind_options(opts) - f = import_function(symname, ctype, argtype, opt[:call_type]) - name = symname.gsub(/@.+/,'') - @func_map[name] = f - # define_method(name){|*args,&block| f.call(*args,&block)} - begin - /^(.+?):(\d+)/ =~ caller.first - file, line = $1, $2.to_i - rescue - file, line = __FILE__, __LINE__+3 - end - module_eval(<<-EOS, file, line) - def #{name}(*args, &block) - @func_map['#{name}'].call(*args,&block) - end - EOS - module_function(name) - f - end - - # Creates a global method from the given C +signature+ using the given - # +opts+ as bind parameters with the given block. - def bind(signature, *opts, &blk) - name, ctype, argtype = parse_signature(signature, type_alias) - h = parse_bind_options(opts) - case h[:callback_type] - when :bind, nil - f = bind_function(name, ctype, argtype, h[:call_type], &blk) - else - raise(RuntimeError, "unknown callback type: #{h[:callback_type]}") - end - @func_map[name] = f - #define_method(name){|*args,&block| f.call(*args,&block)} - begin - /^(.+?):(\d+)/ =~ caller.first - file, line = $1, $2.to_i - rescue - file, line = __FILE__, __LINE__+3 - end - module_eval(<<-EOS, file, line) - def #{name}(*args,&block) - @func_map['#{name}'].call(*args,&block) - end - EOS - module_function(name) - f - end - - # Creates a class to wrap the C struct described by +signature+. - # - # MyStruct = struct ['int i', 'char c'] - def struct(signature) - tys, mems = parse_struct_signature(signature, type_alias) - Fiddle::CStructBuilder.create(CStruct, tys, mems) - end - - # Creates a class to wrap the C union described by +signature+. - # - # MyUnion = union ['int i', 'char c'] - def union(signature) - tys, mems = parse_struct_signature(signature, type_alias) - Fiddle::CStructBuilder.create(CUnion, tys, mems) - end - - # Returns the function mapped to +name+, that was created by either - # Fiddle::Importer.extern or Fiddle::Importer.bind - def [](name) - @func_map[name] - end - - # Creates a class to wrap the C struct with the value +ty+ - # - # See also Fiddle::Importer.struct - def create_value(ty, val=nil) - s = struct([ty + " value"]) - ptr = s.malloc() - if( val ) - ptr.value = val - end - return ptr - end - alias value create_value - - # Returns a new instance of the C struct with the value +ty+ at the +addr+ - # address. - def import_value(ty, addr) - s = struct([ty + " value"]) - ptr = s.new(addr) - return ptr - end - - - # The Fiddle::CompositeHandler instance - # - # Will raise an error if no handlers are open. - def handler - (@handler ||= nil) or raise "call dlload before importing symbols and functions" - end - - # Returns a new Fiddle::Pointer instance at the memory address of the given - # +name+ symbol. - # - # Raises a DLError if the +name+ doesn't exist. - # - # See Fiddle::CompositeHandler.sym and Fiddle::Handle.sym - def import_symbol(name) - addr = handler.sym(name) - if( !addr ) - raise(DLError, "cannot find the symbol: #{name}") - end - Pointer.new(addr) - end - - # Returns a new Fiddle::Function instance at the memory address of the given - # +name+ function. - # - # Raises a DLError if the +name+ doesn't exist. - # - # * +argtype+ is an Array of arguments, passed to the +name+ function. - # * +ctype+ is the return type of the function - # * +call_type+ is the ABI of the function - # - # See also Fiddle:Function.new - # - # See Fiddle::CompositeHandler.sym and Fiddle::Handler.sym - def import_function(name, ctype, argtype, call_type = nil) - addr = handler.sym(name) - if( !addr ) - raise(DLError, "cannot find the function: #{name}()") - end - Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type], - name: name) - end - - # Returns a new closure wrapper for the +name+ function. - # - # * +ctype+ is the return type of the function - # * +argtype+ is an Array of arguments, passed to the callback function - # * +call_type+ is the abi of the closure - # * +block+ is passed to the callback - # - # See Fiddle::Closure - def bind_function(name, ctype, argtype, call_type = nil, &block) - abi = CALL_TYPE_TO_ABI[call_type] - closure = Class.new(Fiddle::Closure) { - define_method(:call, block) - }.new(ctype, argtype, abi) - - Function.new(closure, argtype, ctype, abi, name: name) - end - end -end diff --git a/ext/fiddle/lib/fiddle/pack.rb b/ext/fiddle/lib/fiddle/pack.rb deleted file mode 100644 index b41e36e8e2..0000000000 --- a/ext/fiddle/lib/fiddle/pack.rb +++ /dev/null @@ -1,155 +0,0 @@ -# frozen_string_literal: true -require 'fiddle' - -module Fiddle - module PackInfo # :nodoc: all - ALIGN_MAP = { - TYPE_VOIDP => ALIGN_VOIDP, - TYPE_CHAR => ALIGN_CHAR, - TYPE_SHORT => ALIGN_SHORT, - TYPE_INT => ALIGN_INT, - TYPE_LONG => ALIGN_LONG, - TYPE_FLOAT => ALIGN_FLOAT, - TYPE_DOUBLE => ALIGN_DOUBLE, - 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_CHAR => "c", - TYPE_SHORT => "s!", - TYPE_INT => "i!", - TYPE_LONG => "l!", - TYPE_FLOAT => "f", - TYPE_DOUBLE => "d", - 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 - if RUBY_ENGINE == "jruby" and WINDOWS and [0].pack("l!").size == 8 - # JRuby's 'l!' pack string doesn't use 32-bit on Windows. - # See https://github.com/jruby/jruby/issues/8357 for details - PACK_MAP[TYPE_LONG] = PACK_MAP[TYPE_INT] - PACK_MAP[TYPE_ULONG] = PACK_MAP[TYPE_UINT] - end - - SIZE_MAP = { - TYPE_VOIDP => SIZEOF_VOIDP, - TYPE_CHAR => SIZEOF_CHAR, - TYPE_SHORT => SIZEOF_SHORT, - TYPE_INT => SIZEOF_INT, - TYPE_LONG => SIZEOF_LONG, - TYPE_FLOAT => SIZEOF_FLOAT, - TYPE_DOUBLE => SIZEOF_DOUBLE, - 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_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) - d = addr % align - if( d == 0 ) - addr - else - addr + (align - d) - end - end - module_function :align - end - - class Packer # :nodoc: all - include PackInfo - - def self.[](*types) - new(types) - end - - def initialize(types) - parse_types(types) - end - - def size() - @size - end - - def pack(ary) - case SIZEOF_VOIDP - when SIZEOF_LONG - ary.pack(@template) - else - if defined?(TYPE_LONG_LONG) and - SIZEOF_VOIDP == SIZEOF_LONG_LONG - ary.pack(@template) - else - raise(RuntimeError, "sizeof(void*)?") - end - end - end - - def unpack(ary) - case SIZEOF_VOIDP - when SIZEOF_LONG - ary.join().unpack(@template) - else - if defined?(TYPE_LONG_LONG) and - SIZEOF_VOIDP == SIZEOF_LONG_LONG - ary.join().unpack(@template) - else - raise(RuntimeError, "sizeof(void*)?") - end - end - end - - private - - def parse_types(types) - @template = "".dup - addr = 0 - types.each{|t| - orig_addr = addr - if( t.is_a?(Array) ) - addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP]) - else - addr = align(orig_addr, ALIGN_MAP[t]) - end - d = addr - orig_addr - if( d > 0 ) - @template << "x#{d}" - end - if( t.is_a?(Array) ) - @template << (PACK_MAP[t[0]] * t[1]) - addr += (SIZE_MAP[t[0]] * t[1]) - else - @template << PACK_MAP[t] - addr += SIZE_MAP[t] - end - } - addr = align(addr, ALIGN_MAP[TYPE_VOIDP]) - @size = addr - end - end -end diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb deleted file mode 100644 index e4c2c79ac5..0000000000 --- a/ext/fiddle/lib/fiddle/struct.rb +++ /dev/null @@ -1,560 +0,0 @@ -# frozen_string_literal: true -require 'fiddle' -require 'fiddle/value' -require 'fiddle/pack' - -module Fiddle - # A base class for objects representing a C structure - class CStruct - include Enumerable - - # accessor to Fiddle::CStructEntity - def CStruct.entity_class - CStructEntity - end - - def self.offsetof(name, members, types) # :nodoc: - offset = 0 - worklist = name.split('.') - this_type = self - while search_name = worklist.shift - index = 0 - member_index = members.index(search_name) - - unless member_index - # Possibly a sub-structure - member_index = members.index { |member_name, _| - member_name == search_name - } - return unless member_index - end - - types.each { |type, count = 1| - orig_offset = offset - if type.respond_to?(:entity_class) - align = type.alignment - type_size = type.size - else - align = PackInfo::ALIGN_MAP[type] - type_size = PackInfo::SIZE_MAP[type] - end - - # Unions shouldn't advance the offset - if this_type.entity_class == CUnionEntity - type_size = 0 - end - - offset = PackInfo.align(orig_offset, align) - - if worklist.empty? - return offset if index == member_index - else - if index == member_index - subtype = types[member_index] - members = subtype.members - types = subtype.types - this_type = subtype - break - end - end - - offset += (type_size * count) - index += 1 - } - end - nil - end - - def each - return enum_for(__function__) unless block_given? - - self.class.members.each do |name,| - yield(self[name]) - end - end - - def each_pair - return enum_for(__function__) unless block_given? - - self.class.members.each do |name,| - yield(name, self[name]) - end - end - - def to_h - hash = {} - each_pair do |name, value| - hash[name] = unstruct(value) - end - hash - end - - def replace(another) - if another.nil? - self.class.members.each do |name,| - self[name] = nil - end - elsif another.respond_to?(:each_pair) - another.each_pair do |name, value| - self[name] = value - end - else - another.each do |name, value| - self[name] = value - end - end - self - end - - private - def unstruct(value) - case value - when CStruct - value.to_h - when Array - value.collect do |v| - unstruct(v) - end - else - value - end - end - end - - # A base class for objects representing a C union - class CUnion - # accessor to Fiddle::CUnionEntity - def CUnion.entity_class - CUnionEntity - end - - def self.offsetof(name, members, types) # :nodoc: - 0 - end - end - - # Wrapper for arrays within a struct - class StructArray < Array - include ValueUtil - - def initialize(ptr, type, initial_values) - @ptr = ptr - @type = type - @is_struct = @type.respond_to?(:entity_class) - if @is_struct - super(initial_values) - else - @size = Fiddle::PackInfo::SIZE_MAP[type] - @pack_format = Fiddle::PackInfo::PACK_MAP[type] - super(initial_values.collect { |v| unsigned_value(v, type) }) - end - end - - def to_ptr - @ptr - end - - def []=(index, value) - if index < 0 || index >= size - raise IndexError, 'index %d outside of array bounds 0...%d' % [index, size] - end - - if @is_struct - self[index].replace(value) - else - to_ptr[index * @size, @size] = [value].pack(@pack_format) - super(index, value) - end - end - end - - # Used to construct C classes (CUnion, CStruct, etc) - # - # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an - # easy-to-use manner. - module CStructBuilder - # Construct a new class given a C: - # * class +klass+ (CUnion, CStruct, or other that provide an - # #entity_class) - # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types - # constants) - # * corresponding +members+ - # - # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an - # easy-to-use manner. - # - # Examples: - # - # require 'fiddle/struct' - # require 'fiddle/cparser' - # - # include Fiddle::CParser - # - # types, members = parse_struct_signature(['int i','char c']) - # - # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) - # - # MyStruct.malloc(Fiddle::RUBY_FREE) do |obj| - # ... - # end - # - # obj = MyStruct.malloc(Fiddle::RUBY_FREE) - # begin - # ... - # ensure - # obj.call_free - # end - # - # obj = MyStruct.malloc - # begin - # ... - # ensure - # Fiddle.free obj.to_ptr - # end - # - def create(klass, types, members) - new_class = Class.new(klass){ - define_method(:initialize){|addr, func = nil| - if addr.is_a?(self.class.entity_class) - @entity = addr - else - @entity = self.class.entity_class.new(addr, types, func) - end - @entity.assign_names(members) - } - define_method(:[]) { |*args| @entity.send(:[], *args) } - define_method(:[]=) { |*args| @entity.send(:[]=, *args) } - define_method(:to_ptr){ @entity } - define_method(:to_i){ @entity.to_i } - define_singleton_method(:types) { types } - define_singleton_method(:members) { members } - - # Return the offset of a struct member given its name. - # For example: - # - # MyStruct = struct [ - # "int64_t i", - # "char c", - # ] - # - # MyStruct.offsetof("i") # => 0 - # MyStruct.offsetof("c") # => 8 - # - define_singleton_method(:offsetof) { |name| - klass.offsetof(name, members, types) - } - members.each{|name| - name = name[0] if name.is_a?(Array) # name is a nested struct - next if method_defined?(name) - define_method(name){ @entity[name] } - define_method(name + "="){|val| @entity[name] = val } - } - entity_class = klass.entity_class - alignment = entity_class.alignment(types) - size = entity_class.size(types) - define_singleton_method(:alignment) { alignment } - define_singleton_method(:size) { size } - define_singleton_method(:malloc) do |func=nil, &block| - if block - entity_class.malloc(types, func, size) do |entity| - block.call(new(entity)) - end - else - new(entity_class.malloc(types, func, size)) - end - end - } - return new_class - end - module_function :create - end - - # A pointer to a C structure - class CStructEntity < Fiddle::Pointer - include PackInfo - include ValueUtil - - def CStructEntity.alignment(types) - max = 1 - types.each do |type, count = 1| - if type.respond_to?(:entity_class) - n = type.alignment - else - n = ALIGN_MAP[type] - end - max = n if n > max - end - max - end - - # Allocates a C struct with the +types+ provided. - # - # See Fiddle::Pointer.malloc for memory management issues. - def CStructEntity.malloc(types, func = nil, size = size(types)) - if block_given? and func.nil? - message = "a free function must be supplied to #{self}.malloc " + - "when it is called with a block" - raise ArgumentError, message - end - - pointer = Pointer.malloc(size) - begin - struct = new(pointer, types, func) - rescue - pointer.free = func - pointer.call_free - raise - end - if block_given? - begin - yield(struct) - ensure - struct.call_free - end - else - struct - end - end - - # Returns the offset for the packed sizes for the given +types+. - # - # Fiddle::CStructEntity.size( - # [ Fiddle::TYPE_DOUBLE, - # Fiddle::TYPE_INT, - # Fiddle::TYPE_CHAR, - # Fiddle::TYPE_VOIDP ]) #=> 24 - def CStructEntity.size(types) - offset = 0 - - max_align = types.map { |type, count = 1| - last_offset = offset - - if type.respond_to?(:entity_class) - align = type.alignment - type_size = type.size - else - align = PackInfo::ALIGN_MAP[type] - type_size = PackInfo::SIZE_MAP[type] - end - offset = PackInfo.align(last_offset, align) + - (type_size * count) - - align - }.max - - PackInfo.align(offset, max_align) - end - - # Wraps the C pointer +addr+ as a C struct with the given +types+. - # - # When the instance is garbage collected, the C function +func+ is called. - # - # See also Fiddle::Pointer.new - def initialize(addr, types, func = nil) - if func && addr.is_a?(Pointer) && addr.free - raise ArgumentError, 'free function specified on both underlying struct Pointer and when creating a CStructEntity - who do you want to free this?' - end - set_ctypes(types) - super(addr, @size, func) - end - - # Set the names of the +members+ in this C struct - def assign_names(members) - @members = [] - @nested_structs = {} - members.each_with_index do |member, index| - if member.is_a?(Array) # nested struct - member_name = member[0] - struct_type, struct_count = @ctypes[index] - if struct_count.nil? - struct = struct_type.new(to_i + @offset[index]) - else - structs = struct_count.times.map do |i| - struct_type.new(to_i + @offset[index] + i * struct_type.size) - end - struct = StructArray.new(to_i + @offset[index], - struct_type, - structs) - end - @nested_structs[member_name] = struct - else - member_name = member - end - @members << member_name - end - end - - # Calculates the offsets and sizes for the given +types+ in the struct. - def set_ctypes(types) - @ctypes = types - @offset = [] - offset = 0 - - max_align = types.map { |type, count = 1| - orig_offset = offset - if type.respond_to?(:entity_class) - align = type.alignment - type_size = type.size - else - align = ALIGN_MAP[type] - type_size = SIZE_MAP[type] - end - offset = PackInfo.align(orig_offset, align) - - @offset << offset - - offset += (type_size * count) - - align - }.max - - @size = PackInfo.align(offset, max_align) - end - - # Fetch struct member +name+ if only one argument is specified. If two - # arguments are specified, the first is an offset and the second is a - # length and this method returns the string of +length+ bytes beginning at - # +offset+. - # - # Examples: - # - # my_struct = struct(['int id']).malloc - # my_struct.id = 1 - # my_struct['id'] # => 1 - # my_struct[0, 4] # => "\x01\x00\x00\x00".b - # - def [](*args) - return super(*args) if args.size > 1 - name = args[0] - idx = @members.index(name) - if( idx.nil? ) - raise(ArgumentError, "no such member: #{name}") - end - ty = @ctypes[idx] - if( ty.is_a?(Array) ) - if ty.first.respond_to?(:entity_class) - return @nested_structs[name] - else - r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) - end - elsif ty.respond_to?(:entity_class) - return @nested_structs[name] - else - r = super(@offset[idx], SIZE_MAP[ty.abs]) - end - packer = Packer.new([ty]) - val = packer.unpack([r]) - case ty - when Array - case ty[0] - when TYPE_VOIDP - val = val.collect{|v| Pointer.new(v)} - end - when TYPE_VOIDP - val = Pointer.new(val[0]) - else - val = val[0] - end - if( ty.is_a?(Integer) && (ty < 0) ) - return unsigned_value(val, ty) - elsif( ty.is_a?(Array) && (ty[0] < 0) ) - return StructArray.new(self + @offset[idx], ty[0], val) - else - return val - end - end - - # Set struct member +name+, to value +val+. If more arguments are - # specified, writes the string of bytes to the memory at the given - # +offset+ and +length+. - # - # Examples: - # - # my_struct = struct(['int id']).malloc - # my_struct['id'] = 1 - # my_struct[0, 4] = "\x01\x00\x00\x00".b - # my_struct.id # => 1 - # - def []=(*args) - return super(*args) if args.size > 2 - name, val = *args - name = name.to_s if name.is_a?(Symbol) - nested_struct = @nested_structs[name] - if nested_struct - if nested_struct.is_a?(StructArray) - if val.nil? - nested_struct.each do |s| - s.replace(nil) - end - else - val.each_with_index do |v, i| - nested_struct[i] = v - end - end - else - nested_struct.replace(val) - end - return val - end - idx = @members.index(name) - if( idx.nil? ) - raise(ArgumentError, "no such member: #{name}") - end - ty = @ctypes[idx] - packer = Packer.new([ty]) - val = wrap_arg(val, ty, []) - buff = packer.pack([val].flatten()) - super(@offset[idx], buff.size, buff) - if( ty.is_a?(Integer) && (ty < 0) ) - return unsigned_value(val, ty) - elsif( ty.is_a?(Array) && (ty[0] < 0) ) - return val.collect{|v| unsigned_value(v,ty[0])} - else - return val - end - end - - undef_method :size= - def to_s() # :nodoc: - super(@size) - end - - def +(delta) - Pointer.new(to_i + delta, @size - delta) - end - - def -(delta) - Pointer.new(to_i - delta, @size + delta) - end - end - - # A pointer to a C union - class CUnionEntity < CStructEntity - include PackInfo - - # Returns the size needed for the union with the given +types+. - # - # Fiddle::CUnionEntity.size( - # [ Fiddle::TYPE_DOUBLE, - # Fiddle::TYPE_INT, - # Fiddle::TYPE_CHAR, - # Fiddle::TYPE_VOIDP ]) #=> 8 - def CUnionEntity.size(types) - types.map { |type, count = 1| - if type.respond_to?(:entity_class) - type.size * count - else - PackInfo::SIZE_MAP[type] * count - end - }.max - end - - # Calculate the necessary offset and for each union member with the given - # +types+ - def set_ctypes(types) - @ctypes = types - @offset = Array.new(types.length, 0) - @size = self.class.size types - end - end -end diff --git a/ext/fiddle/lib/fiddle/types.rb b/ext/fiddle/lib/fiddle/types.rb deleted file mode 100644 index 7baf31ec9e..0000000000 --- a/ext/fiddle/lib/fiddle/types.rb +++ /dev/null @@ -1,73 +0,0 @@ -# frozen_string_literal: true -module Fiddle - # Adds Windows type aliases to the including class for use with - # Fiddle::Importer. - # - # The aliases added are: - # * ATOM - # * BOOL - # * BYTE - # * DWORD - # * DWORD32 - # * DWORD64 - # * HANDLE - # * HDC - # * HINSTANCE - # * HWND - # * LPCSTR - # * LPSTR - # * PBYTE - # * PDWORD - # * PHANDLE - # * PVOID - # * PWORD - # * UCHAR - # * UINT - # * ULONG - # * WORD - module Win32Types - def included(m) # :nodoc: - # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types - m.module_eval{ - typealias "ATOM", "WORD" - typealias "BOOL", "int" - typealias "BYTE", "unsigned char" - typealias "DWORD", "unsigned long" - typealias "DWORD32", "uint32_t" - typealias "DWORD64", "uint64_t" - typealias "HANDLE", "PVOID" - typealias "HDC", "HANDLE" - typealias "HINSTANCE", "HANDLE" - typealias "HWND", "HANDLE" - typealias "LPCSTR", "const char *" - typealias "LPSTR", "char *" - typealias "PBYTE", "BYTE *" - typealias "PDWORD", "DWORD *" - typealias "PHANDLE", "HANDLE *" - typealias "PVOID", "void *" - typealias "PWORD", "WORD *" - typealias "UCHAR", "unsigned char" - typealias "UINT", "unsigned int" - typealias "ULONG", "unsigned long" - typealias "WORD", "unsigned short" - } - end - module_function :included - end - - # Adds basic type aliases to the including class for use with Fiddle::Importer. - # - # The aliases added are +uint+ and +u_int+ (<tt>unsigned int</tt>) and - # +ulong+ and +u_long+ (<tt>unsigned long</tt>) - module BasicTypes - def included(m) # :nodoc: - m.module_eval{ - typealias "uint", "unsigned int" - typealias "u_int", "unsigned int" - typealias "ulong", "unsigned long" - typealias "u_long", "unsigned long" - } - end - module_function :included - end -end diff --git a/ext/fiddle/lib/fiddle/value.rb b/ext/fiddle/lib/fiddle/value.rb deleted file mode 100644 index 5f0b2e951e..0000000000 --- a/ext/fiddle/lib/fiddle/value.rb +++ /dev/null @@ -1,120 +0,0 @@ -# frozen_string_literal: true -require 'fiddle' - -module Fiddle - module ValueUtil #:nodoc: all - def unsigned_value(val, ty) - case ty.abs - when TYPE_CHAR - [val].pack("c").unpack1("C") - when TYPE_SHORT - [val].pack("s!").unpack1("S!") - when TYPE_INT - [val].pack("i!").unpack1("I!") - when TYPE_LONG - [val].pack("l!").unpack1("L!") - else - if defined?(TYPE_LONG_LONG) and - ty.abs == TYPE_LONG_LONG - [val].pack("q").unpack1("Q") - else - val - end - end - end - - def signed_value(val, ty) - case ty.abs - when TYPE_CHAR - [val].pack("C").unpack1("c") - when TYPE_SHORT - [val].pack("S!").unpack1("s!") - when TYPE_INT - [val].pack("I!").unpack1("i!") - when TYPE_LONG - [val].pack("L!").unpack1("l!") - else - if defined?(TYPE_LONG_LONG) and - ty.abs == TYPE_LONG_LONG - [val].pack("Q").unpack1("q") - else - val - end - end - end - - def wrap_args(args, tys, funcs, &block) - result = [] - tys ||= [] - args.each_with_index{|arg, idx| - result.push(wrap_arg(arg, tys[idx], funcs, &block)) - } - result - end - - def wrap_arg(arg, ty, funcs = [], &block) - funcs ||= [] - case arg - when nil - return 0 - when Pointer - return arg.to_i - when IO - case ty - when TYPE_VOIDP - return Pointer[arg].to_i - else - return arg.to_i - end - when Function - if( block ) - arg.bind_at_call(&block) - funcs.push(arg) - elsif !arg.bound? - raise(RuntimeError, "block must be given.") - end - return arg.to_i - when String - if( ty.is_a?(Array) ) - return arg.unpack('C*') - else - case SIZEOF_VOIDP - when SIZEOF_LONG - return [arg].pack("p").unpack1("l!") - else - if defined?(SIZEOF_LONG_LONG) and - SIZEOF_VOIDP == SIZEOF_LONG_LONG - return [arg].pack("p").unpack1("q") - else - raise(RuntimeError, "sizeof(void*)?") - end - end - end - when Float, Integer - return arg - when Array - if( ty.is_a?(Array) ) # used only by struct - case ty[0] - when TYPE_VOIDP - return arg.collect{|v| Integer(v)} - when TYPE_CHAR - if( arg.is_a?(String) ) - return val.unpack('C*') - end - end - end - return arg - else - if( arg.respond_to?(:to_ptr) ) - return arg.to_ptr.to_i - else - begin - return Integer(arg) - rescue - raise(ArgumentError, "unknown argument type: #{arg.class}") - end - end - end - end - end -end diff --git a/ext/fiddle/lib/fiddle/version.rb b/ext/fiddle/lib/fiddle/version.rb deleted file mode 100644 index ed0404c210..0000000000 --- a/ext/fiddle/lib/fiddle/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Fiddle - VERSION = "1.1.7.dev" -end diff --git a/ext/fiddle/memory_view.c b/ext/fiddle/memory_view.c deleted file mode 100644 index 5fd7b9b408..0000000000 --- a/ext/fiddle/memory_view.c +++ /dev/null @@ -1,326 +0,0 @@ -#include <fiddle.h> - -#ifdef HAVE_RUBY_MEMORY_VIEW_H - -#include <stdbool.h> -#include <ruby/ruby.h> -#include <ruby/encoding.h> -#include <ruby/memory_view.h> - -#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG -# define INTPTR2NUM LL2NUM -# define UINTPTR2NUM ULL2NUM -#elif SIZEOF_INTPTR_T == SIZEOF_LONG -# define INTPTR2NUM LONG2NUM -# define UINTPTR2NUM ULONG2NUM -#else -# define INTPTR2NUM INT2NUM -# define UINTPTR2NUM UINT2NUM -#endif - -VALUE rb_cMemoryView = Qnil; - -struct memview_data { - rb_memory_view_t view; - rb_memory_view_item_component_t *members; - size_t n_members; -}; - -static void -fiddle_memview_mark(void *ptr) -{ - const struct memview_data *data = ptr; - rb_gc_mark(data->view.obj); -} - -static void -fiddle_memview_release(struct memview_data *data) -{ - if (NIL_P(data->view.obj)) return; - - rb_memory_view_release(&data->view); - data->view.obj = Qnil; - data->view.byte_size = 0; - if (data->members) { - xfree(data->members); - data->members = NULL; - data->n_members = 0; - } -} - -static void -fiddle_memview_free(void *ptr) -{ - struct memview_data *data = ptr; - fiddle_memview_release(data); - xfree(ptr); -} - -static size_t -fiddle_memview_memsize(const void *ptr) -{ - const struct memview_data *data = ptr; - return sizeof(*data) + sizeof(rb_memory_view_item_component_t)*data->n_members + (size_t)data->view.byte_size; -} - -static const rb_data_type_t fiddle_memview_data_type = { - .wrap_struct_name = "fiddle/memory_view", - .function = { - .dmark = fiddle_memview_mark, - .dfree = fiddle_memview_free, - .dsize = fiddle_memview_memsize, - }, - .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, -}; - -static VALUE -rb_fiddle_memview_s_allocate(VALUE klass) -{ - struct memview_data *data; - VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data); - data->view.obj = Qnil; - data->view.byte_size = 0; - data->members = NULL; - data->n_members = 0; - return obj; -} - -static VALUE -rb_fiddle_memview_release(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - fiddle_memview_release(data); - return Qnil; -} - -static VALUE -rb_fiddle_memview_s_export(VALUE klass, VALUE target) -{ - ID id_new; - CONST_ID(id_new, "new"); - VALUE memview = rb_funcall(klass, id_new, 1, target); - return rb_ensure(rb_yield, memview, rb_fiddle_memview_release, memview); -} - -static VALUE -rb_fiddle_memview_initialize(VALUE obj, VALUE target) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (!rb_memory_view_get(target, &data->view, 0)) { - data->view.obj = Qnil; - rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target); - } - - return Qnil; -} - -static VALUE -rb_fiddle_memview_get_obj(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - return data->view.obj; -} - -static VALUE -rb_fiddle_memview_get_byte_size(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return SSIZET2NUM(data->view.byte_size); -} - -static VALUE -rb_fiddle_memview_get_readonly(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return data->view.readonly ? Qtrue : Qfalse; -} - -static VALUE -rb_fiddle_memview_get_format(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return data->view.format == NULL ? Qnil : rb_str_new_cstr(data->view.format); -} - -static VALUE -rb_fiddle_memview_get_item_size(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return SSIZET2NUM(data->view.item_size); -} - -static VALUE -rb_fiddle_memview_get_ndim(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return SSIZET2NUM(data->view.ndim); -} - -static VALUE -rb_fiddle_memview_get_shape(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - if (data->view.shape == NULL) return Qnil; - - const ssize_t ndim = data->view.ndim; - VALUE shape = rb_ary_new_capa(ndim); - ssize_t i; - for (i = 0; i < ndim; ++i) { - rb_ary_push(shape, SSIZET2NUM(data->view.shape[i])); - } - return shape; -} - -static VALUE -rb_fiddle_memview_get_strides(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - if (data->view.strides == NULL) return Qnil; - - const ssize_t ndim = data->view.ndim; - VALUE strides = rb_ary_new_capa(ndim); - ssize_t i; - for (i = 0; i < ndim; ++i) { - rb_ary_push(strides, SSIZET2NUM(data->view.strides[i])); - } - return strides; -} - -static VALUE -rb_fiddle_memview_get_sub_offsets(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - if (data->view.sub_offsets == NULL) return Qnil; - - const ssize_t ndim = data->view.ndim; - VALUE sub_offsets = rb_ary_new_capa(ndim); - ssize_t i; - for (i = 0; i < ndim; ++i) { - rb_ary_push(sub_offsets, SSIZET2NUM(data->view.sub_offsets[i])); - } - return sub_offsets; -} - -static VALUE -rb_fiddle_memview_aref(int argc, VALUE *argv, VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - - const ssize_t ndim = data->view.ndim; - if (argc != ndim) { - rb_raise(rb_eIndexError, "wrong number of index (%d for %"PRIdSIZE")", argc, ndim); - } - - VALUE indices_v = 0; - ssize_t *indices = ALLOCV_N(ssize_t, indices_v, ndim); - - ssize_t i; - for (i = 0; i < ndim; ++i) { - ssize_t x = NUM2SSIZET(argv[i]); - indices[i] = x; - } - - uint8_t *ptr = rb_memory_view_get_item_pointer(&data->view, indices); - ALLOCV_END(indices_v); - - if (data->view.format == NULL) { - return INT2FIX(*ptr); - } - - if (!data->members) { - const char *err; - if (rb_memory_view_parse_item_format(data->view.format, &data->members, &data->n_members, &err) < 0) { - rb_raise(rb_eRuntimeError, "Unable to recognize item format at %"PRIdSIZE" in \"%s\"", - err - data->view.format, data->view.format); - } - } - - return rb_memory_view_extract_item_members(ptr, data->members, data->n_members); -} - -static VALUE -rb_fiddle_memview_to_s(VALUE self) -{ - struct memview_data *data; - const char *raw_data; - long byte_size; - VALUE string; - - TypedData_Get_Struct(self, - struct memview_data, - &fiddle_memview_data_type, - data); - - if (NIL_P(data->view.obj)) { - raw_data = NULL; - byte_size = 0; - } else { - raw_data = data->view.data; - byte_size = data->view.byte_size; - } - - string = rb_enc_str_new_static(raw_data, byte_size, rb_ascii8bit_encoding()); - { - ID id_memory_view; - CONST_ID(id_memory_view, "memory_view"); - rb_ivar_set(string, id_memory_view, self); - } - return rb_obj_freeze(string); -} - -void -Init_fiddle_memory_view(void) -{ - rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject); - rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate); - rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, 1); - rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1); - rb_define_method(rb_cMemoryView, "release", rb_fiddle_memview_release, 0); - rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0); - rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0); - rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0); - rb_define_method(rb_cMemoryView, "format", rb_fiddle_memview_get_format, 0); - rb_define_method(rb_cMemoryView, "item_size", rb_fiddle_memview_get_item_size, 0); - rb_define_method(rb_cMemoryView, "ndim", rb_fiddle_memview_get_ndim, 0); - rb_define_method(rb_cMemoryView, "shape", rb_fiddle_memview_get_shape, 0); - rb_define_method(rb_cMemoryView, "strides", rb_fiddle_memview_get_strides, 0); - rb_define_method(rb_cMemoryView, "sub_offsets", rb_fiddle_memview_get_sub_offsets, 0); - rb_define_method(rb_cMemoryView, "[]", rb_fiddle_memview_aref, -1); - rb_define_method(rb_cMemoryView, "to_s", rb_fiddle_memview_to_s, 0); -} - -#endif /* HAVE_RUBY_MEMORY_VIEW_H */ diff --git a/ext/fiddle/pinned.c b/ext/fiddle/pinned.c deleted file mode 100644 index 94962b0ff6..0000000000 --- a/ext/fiddle/pinned.c +++ /dev/null @@ -1,127 +0,0 @@ -#include <fiddle.h> - -VALUE rb_cPinned; -VALUE rb_eFiddleClearedReferenceError; - -struct pinned_data { - VALUE ptr; -}; - -static void -pinned_mark(void *ptr) -{ - struct pinned_data *data = (struct pinned_data*)ptr; - /* Ensure reference is pinned */ - if (data->ptr) { - rb_gc_mark(data->ptr); - } -} - -static size_t -pinned_memsize(const void *ptr) -{ - return sizeof(struct pinned_data); -} - -static const rb_data_type_t pinned_data_type = { - .wrap_struct_name = "fiddle/pinned", - .function = { - .dmark = pinned_mark, - .dfree = RUBY_TYPED_DEFAULT_FREE, - .dsize = pinned_memsize, - }, - .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, -}; - -static VALUE -allocate(VALUE klass) -{ - struct pinned_data *data; - VALUE obj = TypedData_Make_Struct(klass, struct pinned_data, &pinned_data_type, data); - data->ptr = 0; - return obj; -} - -/* - * call-seq: - * Fiddle::Pinned.new(object) => pinned_object - * - * Create a new pinned object reference. The Fiddle::Pinned instance will - * prevent the GC from moving +object+. - */ -static VALUE -initialize(VALUE self, VALUE ref) -{ - struct pinned_data *data; - TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data); - RB_OBJ_WRITE(self, &data->ptr, ref); - return self; -} - -/* - * call-seq: ref - * - * Return the object that this pinned instance references. - */ -static VALUE -ref(VALUE self) -{ - struct pinned_data *data; - TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data); - if (data->ptr) { - return data->ptr; - } else { - rb_raise(rb_eFiddleClearedReferenceError, "`ref` called on a cleared object"); - } -} - -/* - * call-seq: clear - * - * Clear the reference to the object this is pinning. - */ -static VALUE -clear(VALUE self) -{ - struct pinned_data *data; - TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data); - data->ptr = 0; - return self; -} - -/* - * call-seq: cleared? - * - * Returns true if the reference has been cleared, otherwise returns false. - */ -static VALUE -cleared_p(VALUE self) -{ - struct pinned_data *data; - TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data); - if (data->ptr) { - return Qfalse; - } else { - return Qtrue; - } -} - -extern VALUE rb_eFiddleError; - -void -Init_fiddle_pinned(void) -{ - rb_cPinned = rb_define_class_under(mFiddle, "Pinned", rb_cObject); - rb_define_alloc_func(rb_cPinned, allocate); - rb_define_method(rb_cPinned, "initialize", initialize, 1); - rb_define_method(rb_cPinned, "ref", ref, 0); - rb_define_method(rb_cPinned, "clear", clear, 0); - rb_define_method(rb_cPinned, "cleared?", cleared_p, 0); - - /* - * Document-class: Fiddle::ClearedReferenceError - * - * Cleared reference exception - */ - rb_eFiddleClearedReferenceError = rb_define_class_under(mFiddle, "ClearedReferenceError", rb_eFiddleError); -} diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c deleted file mode 100644 index 10a6cc70ae..0000000000 --- a/ext/fiddle/pointer.c +++ /dev/null @@ -1,888 +0,0 @@ -/* -*- C -*- - * $Id$ - */ - -#include <stdbool.h> -#include <ruby/ruby.h> -#include <ruby/io.h> - -#include <ctype.h> -#include <fiddle.h> - -#ifdef HAVE_RUBY_MEMORY_VIEW_H -# include <ruby/memory_view.h> -#endif - -#ifdef PRIsVALUE -# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) -# define RB_OBJ_STRING(obj) (obj) -#else -# define PRIsVALUE "s" -# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj) -# define RB_OBJ_STRING(obj) StringValueCStr(obj) -#endif - -VALUE rb_cPointer; - -typedef rb_fiddle_freefunc_t freefunc_t; - -struct ptr_data { - void *ptr; - long size; - freefunc_t free; - bool freed; - VALUE wrap[2]; -}; - -#define RPTR_DATA(obj) ((struct ptr_data *)(DATA_PTR(obj))) - -static inline freefunc_t -get_freefunc(VALUE func, volatile VALUE *wrap) -{ - VALUE addrnum; - if (NIL_P(func)) { - *wrap = 0; - return NULL; - } - addrnum = rb_Integer(func); - *wrap = (addrnum != func) ? func : 0; - return (freefunc_t)(VALUE)NUM2PTR(addrnum); -} - -static ID id_to_ptr; - -static void -fiddle_ptr_mark(void *ptr) -{ - struct ptr_data *data = ptr; - if (data->wrap[0]) { - rb_gc_mark(data->wrap[0]); - } - if (data->wrap[1]) { - rb_gc_mark(data->wrap[1]); - } -} - -static void -fiddle_ptr_free_ptr(void *ptr) -{ - struct ptr_data *data = ptr; - if (data->ptr && data->free && !data->freed) { - data->freed = true; - (*(data->free))(data->ptr); - } -} - -static void -fiddle_ptr_free(void *ptr) -{ - fiddle_ptr_free_ptr(ptr); - xfree(ptr); -} - -static size_t -fiddle_ptr_memsize(const void *ptr) -{ - const struct ptr_data *data = ptr; - return sizeof(*data) + data->size; -} - -static const rb_data_type_t fiddle_ptr_data_type = { - .wrap_struct_name = "fiddle/pointer", - .function = { - .dmark = fiddle_ptr_mark, - .dfree = fiddle_ptr_free, - .dsize = fiddle_ptr_memsize, - }, - .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, -}; - -#ifdef HAVE_RUBY_MEMORY_VIEW_H -static struct ptr_data * -fiddle_ptr_check_memory_view(VALUE obj) -{ - struct ptr_data *data; - TypedData_Get_Struct(obj, struct ptr_data, &fiddle_ptr_data_type, data); - if (data->ptr == NULL || data->size == 0) return NULL; - return data; -} - -static bool -fiddle_ptr_memory_view_available_p(VALUE obj) -{ - return fiddle_ptr_check_memory_view(obj) != NULL; -} - -static bool -fiddle_ptr_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags) -{ - struct ptr_data *data = fiddle_ptr_check_memory_view(obj); - rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, true); - - return true; -} - -static const rb_memory_view_entry_t fiddle_ptr_memory_view_entry = { - fiddle_ptr_get_memory_view, - NULL, - fiddle_ptr_memory_view_available_p -}; -#endif - -static VALUE -rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1) -{ - struct ptr_data *data; - VALUE val; - - val = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data); - data->ptr = ptr; - data->free = func; - data->freed = false; - data->size = size; - RB_OBJ_WRITE(val, &data->wrap[0], wrap0); - RB_OBJ_WRITE(val, &data->wrap[1], wrap1); - - return val; -} - -VALUE -rb_fiddle_ptr_new_wrap(void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1) -{ - return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, wrap0, wrap1); -} - -static VALUE -rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func) -{ - return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, 0, 0); -} - -static VALUE -rb_fiddle_ptr_malloc(VALUE klass, long size, freefunc_t func) -{ - void *ptr; - - ptr = ruby_xmalloc((size_t)size); - memset(ptr,0,(size_t)size); - return rb_fiddle_ptr_new2(klass, ptr, size, func, 0, 0); -} - -static void * -rb_fiddle_ptr2cptr(VALUE val) -{ - struct ptr_data *data; - void *ptr; - - if (rb_obj_is_kind_of(val, rb_cPointer)) { - TypedData_Get_Struct(val, struct ptr_data, &fiddle_ptr_data_type, data); - ptr = data->ptr; - } - else if (val == Qnil) { - ptr = NULL; - } - else{ - rb_raise(rb_eTypeError, "Fiddle::Pointer was expected"); - } - - return ptr; -} - -static VALUE -rb_fiddle_ptr_s_allocate(VALUE klass) -{ - VALUE obj; - struct ptr_data *data; - - obj = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data); - data->ptr = 0; - data->size = 0; - data->free = 0; - data->freed = false; - - return obj; -} - -/* - * call-seq: - * Fiddle::Pointer.new(address) => fiddle_cptr - * new(address, size) => fiddle_cptr - * new(address, size, freefunc) => fiddle_cptr - * - * Create a new pointer to +address+ with an optional +size+ and +freefunc+. - * - * +freefunc+ will be called when the instance is garbage collected. - */ -static VALUE -rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self) -{ - VALUE ptr, sym, size, wrap = 0, funcwrap = 0; - struct ptr_data *data; - void *p = NULL; - freefunc_t f = NULL; - long s = 0; - - if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) { - VALUE addrnum = rb_Integer(ptr); - if (addrnum != ptr) wrap = ptr; - p = NUM2PTR(addrnum); - } - if (argc >= 2) { - s = NUM2LONG(size); - } - if (argc >= 3) { - f = get_freefunc(sym, &funcwrap); - } - - if (p) { - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (data->ptr && data->free) { - /* Free previous memory. Use of inappropriate initialize may cause SEGV. */ - (*(data->free))(data->ptr); - } - 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; - } - - return Qnil; -} - -static VALUE -rb_fiddle_ptr_call_free(VALUE self); - -/* - * call-seq: - * Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance - * Fiddle::Pointer.malloc(size, freefunc) { |pointer| ... } => ... - * - * == Examples - * - * # Automatically freeing the pointer when the block is exited - recommended - * Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) do |pointer| - * ... - * end - * - * # Manually freeing but relying on the garbage collector otherwise - * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) - * ... - * pointer.call_free - * - * # Relying on the garbage collector - may lead to unlimited memory allocated before freeing any, but safe - * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) - * ... - * - * # Only manually freeing - * pointer = Fiddle::Pointer.malloc(size) - * begin - * ... - * ensure - * Fiddle.free pointer - * end - * - * # No free function and no call to free - the native memory will leak if the pointer is garbage collected - * pointer = Fiddle::Pointer.malloc(size) - * ... - * - * Allocate +size+ bytes of memory and associate it with an optional - * +freefunc+. - * - * If a block is supplied, the pointer will be yielded to the block instead of - * being returned, and the return value of the block will be returned. A - * +freefunc+ must be supplied if a block is. - * - * If a +freefunc+ is supplied it will be called once, when the pointer is - * garbage collected or when the block is left if a block is supplied or - * when the user calls +call_free+, whichever happens first. +freefunc+ must be - * an address pointing to a function or an instance of +Fiddle::Function+. - */ -static VALUE -rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass) -{ - VALUE size, sym, obj, wrap = 0; - long s; - freefunc_t f; - - switch (rb_scan_args(argc, argv, "11", &size, &sym)) { - case 1: - s = NUM2LONG(size); - f = NULL; - break; - case 2: - s = NUM2LONG(size); - f = get_freefunc(sym, &wrap); - break; - default: - rb_bug("rb_fiddle_ptr_s_malloc"); - } - - obj = rb_fiddle_ptr_malloc(klass, s,f); - if (wrap) RB_OBJ_WRITE(obj, &RPTR_DATA(obj)->wrap[1], wrap); - - if (rb_block_given_p()) { - if (!f) { - rb_raise(rb_eArgError, "a free function must be supplied to Fiddle::Pointer.malloc when it is called with a block"); - } - return rb_ensure(rb_yield, obj, rb_fiddle_ptr_call_free, obj); - } else { - return obj; - } -} - -/* - * call-seq: to_i - * - * Returns the integer memory location of this pointer. - */ -static VALUE -rb_fiddle_ptr_to_i(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return PTR2NUM(data->ptr); -} - -/* - * call-seq: to_value - * - * Cast this pointer to a ruby object. - */ -static VALUE -rb_fiddle_ptr_to_value(VALUE self) -{ - struct ptr_data *data; - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return (VALUE)(data->ptr); -} - -/* - * call-seq: ptr - * - * Returns a new Fiddle::Pointer instance that is a dereferenced pointer for - * this pointer. - * - * Analogous to the star operator in C. - */ -static VALUE -rb_fiddle_ptr_ptr(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return rb_fiddle_ptr_new(*((void**)(data->ptr)),0,0); -} - -/* - * call-seq: ref - * - * Returns a new Fiddle::Pointer instance that is a reference pointer for this - * pointer. - * - * Analogous to the ampersand operator in C. - */ -static VALUE -rb_fiddle_ptr_ref(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return rb_fiddle_ptr_new(&(data->ptr),0,0); -} - -/* - * call-seq: null? - * - * Returns +true+ if this is a null pointer. - */ -static VALUE -rb_fiddle_ptr_null_p(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return data->ptr ? Qfalse : Qtrue; -} - -/* - * call-seq: free=(function) - * - * Set the free function for this pointer to +function+ in the given - * Fiddle::Function. - */ -static VALUE -rb_fiddle_ptr_free_set(VALUE self, VALUE val) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - data->free = get_freefunc(val, &data->wrap[1]); - - return Qnil; -} - -/* - * call-seq: free => Fiddle::Function - * - * Get the free function for this pointer. - * - * Returns a new instance of Fiddle::Function. - * - * See Fiddle::Function.new - */ -static VALUE -rb_fiddle_ptr_free_get(VALUE self) -{ - struct ptr_data *pdata; - VALUE address; - VALUE arg_types; - VALUE ret_type; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata); - - if (!pdata->free) - return Qnil; - - address = PTR2NUM(pdata->free); - ret_type = INT2NUM(TYPE_VOID); - arg_types = rb_ary_new(); - rb_ary_push(arg_types, INT2NUM(TYPE_VOIDP)); - - return rb_fiddle_new_function(address, arg_types, ret_type); -} - -/* - * call-seq: call_free => nil - * - * Call the free function for this pointer. Calling more than once will do - * nothing. Does nothing if there is no free function attached. - */ -static VALUE -rb_fiddle_ptr_call_free(VALUE self) -{ - struct ptr_data *pdata; - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata); - fiddle_ptr_free_ptr(pdata); - return Qnil; -} - -/* - * call-seq: freed? => bool - * - * Returns if the free function for this pointer has been called. - */ -static VALUE -rb_fiddle_ptr_freed_p(VALUE self) -{ - struct ptr_data *pdata; - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata); - return pdata->freed ? Qtrue : Qfalse; -} - -/* - * call-seq: - * - * ptr.to_s => string - * ptr.to_s(len) => string - * - * Returns the pointer contents as a string. - * - * When called with no arguments, this method will return the contents until - * the first NULL byte. - * - * When called with +len+, a string of +len+ bytes will be returned. - * - * See to_str - */ -static VALUE -rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self) -{ - struct ptr_data *data; - VALUE arg1, val; - int len; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - switch (rb_scan_args(argc, argv, "01", &arg1)) { - case 0: - val = rb_str_new2((char*)(data->ptr)); - break; - case 1: - len = NUM2INT(arg1); - val = rb_str_new((char*)(data->ptr), len); - break; - default: - rb_bug("rb_fiddle_ptr_to_s"); - } - - return val; -} - -/* - * call-seq: - * - * ptr.to_str => string - * ptr.to_str(len) => string - * - * Returns the pointer contents as a string. - * - * When called with no arguments, this method will return the contents with the - * length of this pointer's +size+. - * - * When called with +len+, a string of +len+ bytes will be returned. - * - * See to_s - */ -static VALUE -rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self) -{ - struct ptr_data *data; - VALUE arg1, val; - int len; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - switch (rb_scan_args(argc, argv, "01", &arg1)) { - case 0: - val = rb_str_new((char*)(data->ptr),data->size); - break; - case 1: - len = NUM2INT(arg1); - val = rb_str_new((char*)(data->ptr), len); - break; - default: - rb_bug("rb_fiddle_ptr_to_str"); - } - - return val; -} - -/* - * call-seq: inspect - * - * Returns a string formatted with an easily readable representation of the - * internal state of the pointer. - */ -static VALUE -rb_fiddle_ptr_inspect(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>", - RB_OBJ_CLASSNAME(self), (void *)data, data->ptr, data->size, (void *)(VALUE)data->free); -} - -/* - * call-seq: - * ptr == other => true or false - * ptr.eql?(other) => true or false - * - * Returns true if +other+ wraps the same pointer, otherwise returns - * false. - */ -static VALUE -rb_fiddle_ptr_eql(VALUE self, VALUE other) -{ - void *ptr1, *ptr2; - - if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qfalse; - - ptr1 = rb_fiddle_ptr2cptr(self); - ptr2 = rb_fiddle_ptr2cptr(other); - - return ptr1 == ptr2 ? Qtrue : Qfalse; -} - -/* - * call-seq: - * ptr <=> other => -1, 0, 1, or nil - * - * Returns -1 if less than, 0 if equal to, 1 if greater than +other+. - * - * Returns nil if +ptr+ cannot be compared to +other+. - */ -static VALUE -rb_fiddle_ptr_cmp(VALUE self, VALUE other) -{ - void *ptr1, *ptr2; - SIGNED_VALUE diff; - - if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qnil; - - ptr1 = rb_fiddle_ptr2cptr(self); - ptr2 = rb_fiddle_ptr2cptr(other); - diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2; - if (!diff) return INT2FIX(0); - return diff > 0 ? INT2NUM(1) : INT2NUM(-1); -} - -/* - * call-seq: - * ptr + n => new cptr - * - * Returns a new pointer instance that has been advanced +n+ bytes. - */ -static VALUE -rb_fiddle_ptr_plus(VALUE self, VALUE other) -{ - void *ptr; - long num, size; - - ptr = rb_fiddle_ptr2cptr(self); - size = RPTR_DATA(self)->size; - num = NUM2LONG(other); - return rb_fiddle_ptr_new((char *)ptr + num, size - num, 0); -} - -/* - * call-seq: - * ptr - n => new cptr - * - * Returns a new pointer instance that has been moved back +n+ bytes. - */ -static VALUE -rb_fiddle_ptr_minus(VALUE self, VALUE other) -{ - void *ptr; - long num, size; - - ptr = rb_fiddle_ptr2cptr(self); - size = RPTR_DATA(self)->size; - num = NUM2LONG(other); - return rb_fiddle_ptr_new((char *)ptr - num, size + num, 0); -} - -/* - * call-seq: - * ptr[index] -> an_integer - * ptr[start, length] -> a_string - * - * Returns integer stored at _index_. - * - * If _start_ and _length_ are given, a string containing the bytes from - * _start_ of _length_ will be returned. - */ -static VALUE -rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self) -{ - VALUE arg0, arg1; - VALUE retval = Qnil; - size_t offset, len; - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference"); - switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){ - case 1: - offset = NUM2ULONG(arg0); - retval = INT2NUM(*((char *)data->ptr + offset)); - break; - case 2: - offset = NUM2ULONG(arg0); - len = NUM2ULONG(arg1); - retval = rb_str_new((char *)data->ptr + offset, len); - break; - default: - rb_bug("rb_fiddle_ptr_aref()"); - } - return retval; -} - -/* - * call-seq: - * ptr[index] = int -> int - * ptr[start, length] = string or cptr or addr -> string or dl_cptr or addr - * - * Set the value at +index+ to +int+. - * - * Or, set the memory at +start+ until +length+ with the contents of +string+, - * the memory from +dl_cptr+, or the memory pointed at by the memory address - * +addr+. - */ -static VALUE -rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self) -{ - VALUE arg0, arg1, arg2; - VALUE retval = Qnil; - size_t offset, len; - void *mem; - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference"); - switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){ - case 2: - offset = NUM2ULONG(arg0); - ((char*)data->ptr)[offset] = NUM2UINT(arg1); - retval = arg1; - break; - case 3: - offset = NUM2ULONG(arg0); - len = NUM2ULONG(arg1); - if (RB_TYPE_P(arg2, T_STRING)) { - mem = StringValuePtr(arg2); - } - else if( rb_obj_is_kind_of(arg2, rb_cPointer) ){ - mem = rb_fiddle_ptr2cptr(arg2); - } - else{ - mem = NUM2PTR(arg2); - } - memcpy((char *)data->ptr + offset, mem, len); - retval = arg2; - break; - default: - rb_bug("rb_fiddle_ptr_aset()"); - } - return retval; -} - -/* - * call-seq: size=(size) - * - * Set the size of this pointer to +size+ - */ -static VALUE -rb_fiddle_ptr_size_set(VALUE self, VALUE size) -{ - RPTR_DATA(self)->size = NUM2LONG(size); - return size; -} - -/* - * call-seq: size - * - * Get the size of this pointer. - */ -static VALUE -rb_fiddle_ptr_size_get(VALUE self) -{ - return LONG2NUM(RPTR_DATA(self)->size); -} - -/* - * call-seq: - * Fiddle::Pointer[val] => cptr - * to_ptr(val) => cptr - * - * Get the underlying pointer for ruby object +val+ and return it as a - * Fiddle::Pointer object. - */ -static VALUE -rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val) -{ - VALUE ptr, wrap = val, vptr; - - if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){ - rb_io_t *fptr; - FILE *fp; - GetOpenFile(val, fptr); - fp = rb_io_stdio_file(fptr); - ptr = rb_fiddle_ptr_new(fp, 0, NULL); - } - else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){ - char *str = StringValuePtr(val); - wrap = val; - ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL); - } - else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){ - if (rb_obj_is_kind_of(vptr, rb_cPointer)){ - ptr = vptr; - wrap = 0; - } - else{ - rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object"); - } - } - else{ - VALUE num = rb_Integer(val); - if (num == val) wrap = 0; - ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL); - } - 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) -{ - const char *ptr = StringValuePtr(str); - memcpy(NUM2PTR(addr), ptr, RSTRING_LEN(str)); - return str; -} - -void -Init_fiddle_pointer(void) -{ -#undef rb_intern - id_to_ptr = rb_intern("to_ptr"); - - /* Document-class: Fiddle::Pointer - * - * Fiddle::Pointer is a class to handle C pointers - * - */ - rb_cPointer = rb_define_class_under(mFiddle, "Pointer", rb_cObject); - rb_define_alloc_func(rb_cPointer, rb_fiddle_ptr_s_allocate); - 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); - rb_define_method(rb_cPointer, "call_free", rb_fiddle_ptr_call_free, 0); - rb_define_method(rb_cPointer, "freed?", rb_fiddle_ptr_freed_p, 0); - rb_define_method(rb_cPointer, "to_i", rb_fiddle_ptr_to_i, 0); - rb_define_method(rb_cPointer, "to_int", rb_fiddle_ptr_to_i, 0); - rb_define_method(rb_cPointer, "to_value", rb_fiddle_ptr_to_value, 0); - rb_define_method(rb_cPointer, "ptr", rb_fiddle_ptr_ptr, 0); - rb_define_method(rb_cPointer, "+@", rb_fiddle_ptr_ptr, 0); - rb_define_method(rb_cPointer, "ref", rb_fiddle_ptr_ref, 0); - rb_define_method(rb_cPointer, "-@", rb_fiddle_ptr_ref, 0); - rb_define_method(rb_cPointer, "null?", rb_fiddle_ptr_null_p, 0); - rb_define_method(rb_cPointer, "to_s", rb_fiddle_ptr_to_s, -1); - rb_define_method(rb_cPointer, "to_str", rb_fiddle_ptr_to_str, -1); - rb_define_method(rb_cPointer, "inspect", rb_fiddle_ptr_inspect, 0); - rb_define_method(rb_cPointer, "<=>", rb_fiddle_ptr_cmp, 1); - rb_define_method(rb_cPointer, "==", rb_fiddle_ptr_eql, 1); - rb_define_method(rb_cPointer, "eql?", rb_fiddle_ptr_eql, 1); - rb_define_method(rb_cPointer, "+", rb_fiddle_ptr_plus, 1); - rb_define_method(rb_cPointer, "-", rb_fiddle_ptr_minus, 1); - rb_define_method(rb_cPointer, "[]", rb_fiddle_ptr_aref, -1); - rb_define_method(rb_cPointer, "[]=", rb_fiddle_ptr_aset, -1); - rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0); - rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1); - -#ifdef HAVE_RUBY_MEMORY_VIEW_H - rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry); -#endif - - /* Document-const: NULL - * - * A NULL pointer - */ - rb_define_const(mFiddle, "NULL", rb_fiddle_ptr_new(0, 0, 0)); -} diff --git a/gems/bundled_gems b/gems/bundled_gems index e81850b997..254c82d056 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -44,3 +44,4 @@ win32ole 1.9.1 https://github.com/ruby/win32ole irb 1.15.1 https://github.com/ruby/irb 6bb53630c3398b2042fb99d5232c68399491d338 reline 0.6.0 https://github.com/ruby/reline defcd36c0b6e6648333d4b9ab5923eb4e543615e readline 0.0.4 https://github.com/ruby/readline +fiddle 1.1.6 https://github.com/ruby/fiddle diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb deleted file mode 100644 index 457e02f595..0000000000 --- a/test/fiddle/helper.rb +++ /dev/null @@ -1,202 +0,0 @@ -# frozen_string_literal: true - -require 'rbconfig/sizeof' -require 'test/unit' -require 'fiddle' - -puts("Fiddle::VERSION: #{Fiddle::VERSION}") if $VERBOSE - -# FIXME: this is stolen from DL and needs to be refactored. - -libc_so = libm_so = nil - -if RUBY_ENGINE == "jruby" - # "jruby ... [x86_64-linux]" -> "x86_64-linux" - ruby_platform = RUBY_DESCRIPTION.split(" ").last[1..-2] -else - ruby_platform = RUBY_PLATFORM -end -case ruby_platform -when /cygwin/ - libc_so = "cygwin1.dll" - libm_so = "cygwin1.dll" -when /android/ - libdir = '/system/lib' - if [0].pack('L!').size == 8 - libdir = '/system/lib64' - end - libc_so = File.join(libdir, "libc.so") - libm_so = File.join(libdir, "libm.so") -when /linux-musl/ - Dir.glob('/lib/ld-musl-*.so.1') do |ld| - libc_so = libm_so = ld - end -when /linux/ - libdir = '/lib' - case RbConfig::SIZEOF['void*'] - when 4 - # 32-bit ruby - case RUBY_PLATFORM - when /armv\w+-linux/ - # In the ARM 32-bit libc package such as libc6:armhf libc6:armel, - # libc.so and libm.so are installed to /lib/arm-linux-gnu*. - # It's not installed to /lib32. - dir, = Dir.glob('/lib/arm-linux-gnu*') - libdir = dir if dir && File.directory?(dir) - else - libdir = '/lib32' if File.directory? '/lib32' - end - when 8 - # 64-bit ruby - libdir = '/lib64' if File.directory? '/lib64' - end - - # Handle musl libc - libc_so, = Dir.glob(File.join(libdir, "libc.musl*.so*")) - if libc_so - libm_so = libc_so - else - # glibc - case RUBY_PLATFORM - when /alpha-linux/, /ia64-linux/ - libc_so = "libc.so.6.1" - libm_so = "libm.so.6.1" - else - libc_so = "libc.so.6" - libm_so = "libm.so.6" - end - end -when /mingw/, /mswin/ - require "rbconfig" - crtname = RbConfig::CONFIG["RUBY_SO_NAME"][/msvc\w+/] || 'ucrtbase' - libc_so = libm_so = "#{crtname}.dll" -when /darwin/ - libc_so = libm_so = "/usr/lib/libSystem.B.dylib" - # macOS 11.0+ removed libSystem.B.dylib from /usr/lib. But It works with dlopen. - rigid_path = true -when /kfreebsd/ - libc_so = "/lib/libc.so.0.1" - libm_so = "/lib/libm.so.1" -when /gnu/ #GNU/Hurd - libc_so = "/lib/libc.so.0.3" - libm_so = "/lib/libm.so.6" -when /mirbsd/ - libc_so = "/usr/lib/libc.so.41.10" - libm_so = "/usr/lib/libm.so.7.0" -when /freebsd/ - libc_so = "/lib/libc.so.7" - libm_so = "/lib/libm.so.5" -when /bsd|dragonfly/ - libc_so = "/usr/lib/libc.so" - libm_so = "/usr/lib/libm.so" -when /solaris/ - libdir = '/lib' - case RbConfig::SIZEOF['void*'] - when 4 - # 32-bit ruby - libdir = '/lib' if File.directory? '/lib' - when 8 - # 64-bit ruby - libdir = '/lib/64' if File.directory? '/lib/64' - end - libc_so = File.join(libdir, "libc.so") - libm_so = File.join(libdir, "libm.so") -when /aix/ - pwd=Dir.pwd - libc_so = libm_so = "#{pwd}/libaixdltest.so" - unless File.exist? libc_so - cobjs=%w!strcpy.o! - mobjs=%w!floats.o sin.o! - funcs=%w!sin sinf strcpy strncpy! - expfile='dltest.exp' - require 'tmpdir' - Dir.mktmpdir do |_dir| - begin - Dir.chdir _dir - %x!/usr/bin/ar x /usr/lib/libc.a #{cobjs.join(' ')}! - %x!/usr/bin/ar x /usr/lib/libm.a #{mobjs.join(' ')}! - %x!echo "#{funcs.join("\n")}\n" > #{expfile}! - require 'rbconfig' - if RbConfig::CONFIG["GCC"] = 'yes' - lflag='-Wl,' - else - lflag='' - end - flags="#{lflag}-bE:#{expfile} #{lflag}-bnoentry -lm" - %x!#{RbConfig::CONFIG["LDSHARED"]} -o #{libc_so} #{(cobjs+mobjs).join(' ')} #{flags}! - ensure - Dir.chdir pwd - end - end - end -when /haiku/ - libdir = '/system/lib' - case [0].pack('L!').size - when 4 - # 32-bit ruby - libdir = '/system/lib/x86' if File.directory? '/system/lib/x86' - when 8 - # 64-bit ruby - libdir = '/system/lib/' if File.directory? '/system/lib/' - end - libc_so = File.join(libdir, "libroot.so") - libm_so = File.join(libdir, "libroot.so") -else - libc_so = ARGV[0] if ARGV[0] && ARGV[0][0] == ?/ - libm_so = ARGV[1] if ARGV[1] && ARGV[1][0] == ?/ - if( !(libc_so && libm_so) ) - $stderr.puts("libc and libm not found: #{$0} <libc> <libm>") - end -end - -unless rigid_path - libc_so = nil if libc_so && libc_so[0] == ?/ && !File.file?(libc_so) - libm_so = nil if libm_so && libm_so[0] == ?/ && !File.file?(libm_so) -end - -if !libc_so || !libm_so - require "envutil" - ruby = EnvUtil.rubybin - # When the ruby binary is 32-bit and the host is 64-bit, - # `ldd ruby` outputs "not a dynamic executable" message. - # libc_so and libm_so are not set. - ldd = `ldd #{ruby}` - #puts ldd - libc_so = $& if !libc_so && %r{/\S*/libc\.so\S*} =~ ldd - libm_so = $& if !libm_so && %r{/\S*/libm\.so\S*} =~ ldd - #p [libc_so, libm_so] -end - -Fiddle::LIBC_SO = libc_so -Fiddle::LIBM_SO = libm_so - -module Fiddle - class TestCase < Test::Unit::TestCase - def setup - @libc = Fiddle.dlopen(LIBC_SO) - @libm = Fiddle.dlopen(LIBM_SO) - end - - def teardown - if /linux/ =~ RUBY_PLATFORM - GC.start - end - end - - def ffi_backend? - RUBY_ENGINE != 'ruby' - end - - def under_gc_stress - stress, GC.stress = GC.stress, true - yield - ensure - GC.stress = stress - end - - def assert_ractor_shareable(object) - Ractor.make_shareable(object) - assert_operator(Ractor, :shareable?, object) - end - end -end diff --git a/test/fiddle/test_c_struct_builder.rb b/test/fiddle/test_c_struct_builder.rb deleted file mode 100644 index ca44c6cf7a..0000000000 --- a/test/fiddle/test_c_struct_builder.rb +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/struct' - require 'fiddle/cparser' - require 'fiddle/import' -rescue LoadError -end - -module Fiddle - class TestCStructBuilder < TestCase - include Fiddle::CParser - extend Fiddle::Importer - - RBasic = struct ['void * flags', - 'void * klass' ] - - - RObject = struct [ - { 'basic' => RBasic }, - { 'as' => union([ - { 'heap'=> struct([ 'uint32_t numiv', - 'void * ivptr', - 'void * iv_index_tbl' ]) }, - 'void *ary[3]' ])} - ] - - - def test_basic_embedded_members - assert_equal 0, RObject.offsetof("basic.flags") - assert_equal Fiddle::SIZEOF_VOIDP, RObject.offsetof("basic.klass") - end - - def test_embedded_union_members - assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as") - assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap") - assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.numiv") - assert_equal 3 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.ivptr") - assert_equal 4 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.iv_index_tbl") - end - - def test_as_ary - assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.ary") - end - - def test_offsetof - types, members = parse_struct_signature(['int64_t i','char c']) - my_struct = Fiddle::CStructBuilder.create(Fiddle::CStruct, types, members) - assert_equal 0, my_struct.offsetof("i") - assert_equal Fiddle::SIZEOF_INT64_T, my_struct.offsetof("c") - end - - def test_offset_with_gap - types, members = parse_struct_signature(['void *p', 'char c', 'long x']) - my_struct = Fiddle::CStructBuilder.create(Fiddle::CStruct, types, members) - - assert_equal PackInfo.align(0, ALIGN_VOIDP), my_struct.offsetof("p") - assert_equal PackInfo.align(SIZEOF_VOIDP, ALIGN_CHAR), my_struct.offsetof("c") - assert_equal SIZEOF_VOIDP + PackInfo.align(SIZEOF_CHAR, ALIGN_LONG), my_struct.offsetof("x") - end - - def test_union_offsetof - types, members = parse_struct_signature(['int64_t i','char c']) - my_struct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) - assert_equal 0, my_struct.offsetof("i") - assert_equal 0, my_struct.offsetof("c") - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_c_struct_entry.rb b/test/fiddle/test_c_struct_entry.rb deleted file mode 100644 index 45de2efe21..0000000000 --- a/test/fiddle/test_c_struct_entry.rb +++ /dev/null @@ -1,171 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/struct' -rescue LoadError -end - -module Fiddle - class TestCStructEntity < TestCase - def test_class_size - types = [TYPE_DOUBLE, TYPE_CHAR, TYPE_DOUBLE, TYPE_BOOL] - - size = CStructEntity.size types - - alignments = types.map { |type| PackInfo::ALIGN_MAP[type] } - - expected = PackInfo.align 0, alignments[0] - expected += PackInfo::SIZE_MAP[TYPE_DOUBLE] - - expected = PackInfo.align expected, alignments[1] - expected += PackInfo::SIZE_MAP[TYPE_CHAR] - - expected = PackInfo.align expected, alignments[2] - expected += PackInfo::SIZE_MAP[TYPE_DOUBLE] - - expected = PackInfo.align expected, alignments[3] - expected += PackInfo::SIZE_MAP[TYPE_BOOL] - - expected = PackInfo.align expected, alignments.max - - assert_equal expected, size - end - - def test_class_size_with_count - size = CStructEntity.size([[TYPE_DOUBLE, 2], [TYPE_CHAR, 20]]) - - types = [TYPE_DOUBLE, TYPE_CHAR] - alignments = types.map { |type| PackInfo::ALIGN_MAP[type] } - - expected = PackInfo.align 0, alignments[0] - expected += PackInfo::SIZE_MAP[TYPE_DOUBLE] * 2 - - expected = PackInfo.align expected, alignments[1] - expected += PackInfo::SIZE_MAP[TYPE_CHAR] * 20 - - expected = PackInfo.align expected, alignments.max - - assert_equal expected, size - end - - def test_set_ctypes - CStructEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |struct| - struct.assign_names %w[int long] - - # this test is roundabout because the stored ctypes are not accessible - struct['long'] = 1 - struct['int'] = 2 - - assert_equal 1, struct['long'] - assert_equal 2, struct['int'] - end - end - - def test_aref_pointer_array - CStructEntity.malloc([[TYPE_VOIDP, 2]], Fiddle::RUBY_FREE) do |team| - team.assign_names(["names"]) - Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice| - alice[0, 6] = "Alice\0" - Fiddle::Pointer.malloc(4, Fiddle::RUBY_FREE) do |bob| - bob[0, 4] = "Bob\0" - team["names"] = [alice, bob] - assert_equal(["Alice", "Bob"], team["names"].map(&:to_s)) - end - end - end - end - - def test_aref_pointer - CStructEntity.malloc([TYPE_VOIDP], Fiddle::RUBY_FREE) do |user| - user.assign_names(["name"]) - Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice| - alice[0, 6] = "Alice\0" - user["name"] = alice - assert_equal("Alice", user["name"].to_s) - end - end - end - - def test_new_double_free - types = [TYPE_INT] - Pointer.malloc(CStructEntity.size(types), Fiddle::RUBY_FREE) do |pointer| - assert_raise ArgumentError do - CStructEntity.new(pointer, types, Fiddle::RUBY_FREE) - end - end - end - - def test_malloc_block - escaped_struct = nil - returned = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct| - assert_equal Fiddle::SIZEOF_INT, struct.size - assert_equal Fiddle::RUBY_FREE, struct.free.to_i - escaped_struct = struct - :returned - end - assert_equal :returned, returned - assert escaped_struct.freed? - end - - def test_malloc_block_no_free - assert_raise ArgumentError do - CStructEntity.malloc([TYPE_INT]) { |struct| } - end - end - - def test_free - struct = CStructEntity.malloc([TYPE_INT]) - begin - assert_nil struct.free - ensure - Fiddle.free struct - end - end - - def test_free_with_func - struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) - refute struct.freed? - struct.call_free - assert struct.freed? - struct.call_free # you can safely run it again - assert struct.freed? - GC.start # you can safely run the GC routine - assert struct.freed? - end - - def test_free_with_no_func - struct = CStructEntity.malloc([TYPE_INT]) - refute struct.freed? - struct.call_free - refute struct.freed? - struct.call_free # you can safely run it again - refute struct.freed? - end - - def test_freed? - struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) - refute struct.freed? - struct.call_free - assert struct.freed? - end - - def test_null? - struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) - refute struct.null? - end - - def test_size - CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct| - assert_equal Fiddle::SIZEOF_INT, struct.size - end - end - - def test_size= - CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct| - assert_raise NoMethodError do - struct.size = 1 - end - end - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_c_union_entity.rb b/test/fiddle/test_c_union_entity.rb deleted file mode 100644 index e0a3757562..0000000000 --- a/test/fiddle/test_c_union_entity.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/struct' -rescue LoadError -end - - -module Fiddle - class TestCUnionEntity < TestCase - def test_class_size - size = CUnionEntity.size([TYPE_DOUBLE, TYPE_CHAR]) - - assert_equal SIZEOF_DOUBLE, size - end - - def test_class_size_with_count - size = CUnionEntity.size([[TYPE_DOUBLE, 2], [TYPE_CHAR, 20]]) - - assert_equal SIZEOF_CHAR * 20, size - end - - def test_set_ctypes - CUnionEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |union| - union.assign_names %w[int long] - - # this test is roundabout because the stored ctypes are not accessible - union['long'] = 1 - assert_equal 1, union['long'] - - union['int'] = 1 - assert_equal 1, union['int'] - end - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb deleted file mode 100644 index 26cff8e516..0000000000 --- a/test/fiddle/test_closure.rb +++ /dev/null @@ -1,173 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestClosure < Fiddle::TestCase - def teardown - super - # We can't use ObjectSpace with JRuby. - return if RUBY_ENGINE == "jruby" - # Ensure freeing all closures. - # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 . - not_freed_closures = [] - ObjectSpace.each_object(Fiddle::Closure) do |closure| - not_freed_closures << closure unless closure.freed? - end - assert_equal([], not_freed_closures) - end - - def test_argument_errors - assert_raise(TypeError) do - Closure.new(TYPE_INT, TYPE_INT) - end - - assert_raise(TypeError) do - Closure.new('foo', [TYPE_INT]) - end - - assert_raise(TypeError) do - Closure.new(TYPE_INT, ['meow!']) - end - end - - def test_call - closure_class = Class.new(Closure) do - def call - 10 - end - end - closure_class.create(TYPE_INT, []) do |closure| - func = Function.new(closure, [], TYPE_INT) - assert_equal 10, func.call - end - end - - def test_returner - closure_class = Class.new(Closure) do - def call thing - thing - end - end - closure_class.create(TYPE_INT, [TYPE_INT]) do |closure| - func = Function.new(closure, [TYPE_INT], TYPE_INT) - assert_equal 10, func.call(10) - end - end - - def test_const_string - if ffi_backend? - omit("Closure with :const_string works but " + - "Function with :const_string doesn't work with FFI backend") - end - - closure_class = Class.new(Closure) do - def call(string) - @return_string = "Hello! #{string}" - @return_string - end - end - closure_class.create(:const_string, [:const_string]) do |closure| - func = Function.new(closure, [:const_string], :const_string) - assert_equal("Hello! World!", func.call("World!")) - end - end - - def test_bool - closure_class = Class.new(Closure) do - def call(bool) - not bool - end - end - closure_class.create(:bool, [:bool]) do |closure| - func = Function.new(closure, [:bool], :bool) - assert_equal(false, func.call(true)) - end - end - - def test_free - closure_class = Class.new(Closure) do - def call - 10 - end - end - closure_class.create(:int, [:void]) do |closure| - assert(!closure.freed?) - closure.free - assert(closure.freed?) - closure.free - end - end - - def test_block_caller - cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one| - one - end - begin - func = Function.new(cb, [TYPE_INT], TYPE_INT) - assert_equal 11, func.call(11) - ensure - cb.free - end - end - - def test_memsize_ruby_dev_42480 - if RUBY_ENGINE == "jruby" - omit("We can't use ObjectSpace with JRuby") - end - - require 'objspace' - closure_class = Class.new(Closure) do - def call - 10 - end - end - n = 10000 - n.times do - closure_class.create(:int, [:void]) do |closure| - ObjectSpace.memsize_of(closure) - end - end - end - - %w[INT SHORT CHAR LONG LONG_LONG].each do |name| - type = Fiddle.const_get("TYPE_#{name}") rescue next - size = Fiddle.const_get("SIZEOF_#{name}") - [[type, size-1, name], [-type, size, "unsigned_"+name]].each do |t, s, n| - define_method("test_conversion_#{n.downcase}") do - arg = nil - - closure_class = Class.new(Closure) do - define_method(:call) {|x| arg = x} - end - closure_class.create(t, [t]) do |closure| - v = ~(~0 << (8*s)) - - arg = nil - assert_equal(v, closure.call(v)) - assert_equal(arg, v, n) - - arg = nil - func = Function.new(closure, [t], t) - assert_equal(v, func.call(v)) - assert_equal(arg, v, n) - end - end - end - end - - def test_ractor_shareable - omit("Need Ractor") unless defined?(Ractor) - closure_class = Class.new(Closure) do - def call - 0 - end - end - closure_class.create(:int, [:void]) do |c| - assert_ractor_shareable(c) - end - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_cparser.rb b/test/fiddle/test_cparser.rb deleted file mode 100644 index 2052911507..0000000000 --- a/test/fiddle/test_cparser.rb +++ /dev/null @@ -1,419 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/cparser' - require 'fiddle/import' -rescue LoadError -end - -module Fiddle - class TestCParser < TestCase - include CParser - - def test_char_ctype - assert_equal(TYPE_CHAR, parse_ctype('char')) - assert_equal(TYPE_CHAR, parse_ctype('const char')) - assert_equal(TYPE_CHAR, parse_ctype('signed char')) - assert_equal(TYPE_CHAR, parse_ctype('const signed char')) - assert_equal(-TYPE_CHAR, parse_ctype('unsigned char')) - assert_equal(-TYPE_CHAR, parse_ctype('const unsigned char')) - end - - def test_short_ctype - assert_equal(TYPE_SHORT, parse_ctype('short')) - assert_equal(TYPE_SHORT, parse_ctype('const short')) - assert_equal(TYPE_SHORT, parse_ctype('short int')) - assert_equal(TYPE_SHORT, parse_ctype('const short int')) - assert_equal(TYPE_SHORT, parse_ctype('int short')) - assert_equal(TYPE_SHORT, parse_ctype('const int short')) - assert_equal(TYPE_SHORT, parse_ctype('signed short')) - assert_equal(TYPE_SHORT, parse_ctype('const signed short')) - assert_equal(TYPE_SHORT, parse_ctype('short signed')) - assert_equal(TYPE_SHORT, parse_ctype('const short signed')) - assert_equal(TYPE_SHORT, parse_ctype('signed short int')) - assert_equal(TYPE_SHORT, parse_ctype('const signed short int')) - assert_equal(TYPE_SHORT, parse_ctype('signed int short')) - assert_equal(TYPE_SHORT, parse_ctype('const signed int short')) - assert_equal(TYPE_SHORT, parse_ctype('int signed short')) - assert_equal(TYPE_SHORT, parse_ctype('const int signed short')) - assert_equal(TYPE_SHORT, parse_ctype('int short signed')) - assert_equal(TYPE_SHORT, parse_ctype('const int short signed')) - assert_equal(-TYPE_SHORT, parse_ctype('unsigned short')) - assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short')) - assert_equal(-TYPE_SHORT, parse_ctype('unsigned short int')) - assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short int')) - assert_equal(-TYPE_SHORT, parse_ctype('unsigned int short')) - assert_equal(-TYPE_SHORT, parse_ctype('const unsigned int short')) - assert_equal(-TYPE_SHORT, parse_ctype('short int unsigned')) - assert_equal(-TYPE_SHORT, parse_ctype('const short int unsigned')) - assert_equal(-TYPE_SHORT, parse_ctype('int unsigned short')) - assert_equal(-TYPE_SHORT, parse_ctype('const int unsigned short')) - assert_equal(-TYPE_SHORT, parse_ctype('int short unsigned')) - assert_equal(-TYPE_SHORT, parse_ctype('const int short unsigned')) - end - - def test_int_ctype - assert_equal(TYPE_INT, parse_ctype('int')) - assert_equal(TYPE_INT, parse_ctype('const int')) - assert_equal(TYPE_INT, parse_ctype('signed int')) - assert_equal(TYPE_INT, parse_ctype('const signed int')) - assert_equal(-TYPE_INT, parse_ctype('uint')) - assert_equal(-TYPE_INT, parse_ctype('const uint')) - assert_equal(-TYPE_INT, parse_ctype('unsigned int')) - assert_equal(-TYPE_INT, parse_ctype('const unsigned int')) - end - - def test_long_ctype - assert_equal(TYPE_LONG, parse_ctype('long')) - assert_equal(TYPE_LONG, parse_ctype('const long')) - assert_equal(TYPE_LONG, parse_ctype('long int')) - assert_equal(TYPE_LONG, parse_ctype('const long int')) - assert_equal(TYPE_LONG, parse_ctype('int long')) - assert_equal(TYPE_LONG, parse_ctype('const int long')) - assert_equal(TYPE_LONG, parse_ctype('signed long')) - assert_equal(TYPE_LONG, parse_ctype('const signed long')) - assert_equal(TYPE_LONG, parse_ctype('signed long int')) - assert_equal(TYPE_LONG, parse_ctype('const signed long int')) - assert_equal(TYPE_LONG, parse_ctype('signed int long')) - assert_equal(TYPE_LONG, parse_ctype('const signed int long')) - assert_equal(TYPE_LONG, parse_ctype('long signed')) - assert_equal(TYPE_LONG, parse_ctype('const long signed')) - assert_equal(TYPE_LONG, parse_ctype('long int signed')) - assert_equal(TYPE_LONG, parse_ctype('const long int signed')) - assert_equal(TYPE_LONG, parse_ctype('int long signed')) - assert_equal(TYPE_LONG, parse_ctype('const int long signed')) - assert_equal(-TYPE_LONG, parse_ctype('unsigned long')) - assert_equal(-TYPE_LONG, parse_ctype('const unsigned long')) - assert_equal(-TYPE_LONG, parse_ctype('unsigned long int')) - assert_equal(-TYPE_LONG, parse_ctype('const unsigned long int')) - assert_equal(-TYPE_LONG, parse_ctype('long int unsigned')) - assert_equal(-TYPE_LONG, parse_ctype('const long int unsigned')) - assert_equal(-TYPE_LONG, parse_ctype('unsigned int long')) - assert_equal(-TYPE_LONG, parse_ctype('const unsigned int long')) - assert_equal(-TYPE_LONG, parse_ctype('int unsigned long')) - assert_equal(-TYPE_LONG, parse_ctype('const int unsigned long')) - assert_equal(-TYPE_LONG, parse_ctype('int long unsigned')) - assert_equal(-TYPE_LONG, parse_ctype('const int long unsigned')) - end - - def test_size_t_ctype - assert_equal(TYPE_SIZE_T, parse_ctype("size_t")) - assert_equal(TYPE_SIZE_T, parse_ctype("const size_t")) - end - - def test_ssize_t_ctype - assert_equal(TYPE_SSIZE_T, parse_ctype("ssize_t")) - assert_equal(TYPE_SSIZE_T, parse_ctype("const ssize_t")) - end - - def test_ptrdiff_t_ctype - assert_equal(TYPE_PTRDIFF_T, parse_ctype("ptrdiff_t")) - assert_equal(TYPE_PTRDIFF_T, parse_ctype("const ptrdiff_t")) - end - - def test_intptr_t_ctype - assert_equal(TYPE_INTPTR_T, parse_ctype("intptr_t")) - assert_equal(TYPE_INTPTR_T, parse_ctype("const intptr_t")) - end - - def test_uintptr_t_ctype - assert_equal(TYPE_UINTPTR_T, parse_ctype("uintptr_t")) - assert_equal(TYPE_UINTPTR_T, parse_ctype("const uintptr_t")) - end - - def test_bool_ctype - assert_equal(TYPE_BOOL, parse_ctype('bool')) - end - - def test_undefined_ctype - assert_raise(DLError) { parse_ctype('DWORD') } - end - - def test_undefined_ctype_with_type_alias - assert_equal(-TYPE_LONG, - parse_ctype('DWORD', {"DWORD" => "unsigned long"})) - assert_equal(-TYPE_LONG, - parse_ctype('const DWORD', {"DWORD" => "unsigned long"})) - end - - def expand_struct_types(types) - types.collect do |type| - case type - when Class - [expand_struct_types(type.types)] - when Array - [expand_struct_types([type[0]])[0][0], type[1]] - else - type - end - end - end - - def test_struct_basic - assert_equal([[TYPE_INT, TYPE_CHAR], ['i', 'c']], - parse_struct_signature(['int i', 'char c'])) - assert_equal([[TYPE_INT, TYPE_CHAR], ['i', 'c']], - parse_struct_signature(['const int i', 'const char c'])) - end - - def test_struct_array - assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], - ['buffer', 'x']], - parse_struct_signature(['char buffer[80]', - 'int[5] x'])) - assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], - ['buffer', 'x']], - parse_struct_signature(['const char buffer[80]', - 'const int[5] x'])) - end - - def test_struct_nested_struct - types, members = parse_struct_signature([ - 'int x', - {inner: ['int i', 'char c']}, - ]) - assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]], - ['x', ['inner', ['i', 'c']]]], - [expand_struct_types(types), - members]) - end - - def test_struct_nested_defined_struct - inner = Fiddle::Importer.struct(['int i', 'char c']) - assert_equal([[TYPE_INT, inner], - ['x', ['inner', ['i', 'c']]]], - parse_struct_signature([ - 'int x', - {inner: inner}, - ])) - end - - def test_struct_double_nested_struct - types, members = parse_struct_signature([ - 'int x', - { - outer: [ - 'int y', - {inner: ['int i', 'char c']}, - ], - }, - ]) - assert_equal([[TYPE_INT, [[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]]]], - ['x', ['outer', ['y', ['inner', ['i', 'c']]]]]], - [expand_struct_types(types), - members]) - end - - def test_struct_nested_struct_array - types, members = parse_struct_signature([ - 'int x', - { - 'inner[2]' => [ - 'int i', - 'char c', - ], - }, - ]) - assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]], - ['x', ['inner', ['i', 'c']]]], - [expand_struct_types(types), - members]) - end - - def test_struct_double_nested_struct_inner_array - types, members = parse_struct_signature(outer: [ - 'int x', - { - 'inner[2]' => [ - 'int i', - 'char c', - ], - }, - ]) - assert_equal([[[[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]]]], - [['outer', ['x', ['inner', ['i', 'c']]]]]], - [expand_struct_types(types), - members]) - end - - def test_struct_double_nested_struct_outer_array - types, members = parse_struct_signature([ - 'int x', - { - 'outer[2]' => { - inner: [ - 'int i', - 'char c', - ], - }, - }, - ]) - assert_equal([[TYPE_INT, [[[[TYPE_INT, TYPE_CHAR]]], 2]], - ['x', ['outer', [['inner', ['i', 'c']]]]]], - [expand_struct_types(types), - members]) - end - - def test_struct_array_str - assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], - ['buffer', 'x']], - parse_struct_signature('char buffer[80], int[5] x')) - assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], - ['buffer', 'x']], - parse_struct_signature('const char buffer[80], const int[5] x')) - end - - def test_struct_function_pointer - assert_equal([[TYPE_VOIDP], ['cb']], - parse_struct_signature(['void (*cb)(const char*)'])) - end - - def test_struct_function_pointer_str - assert_equal([[TYPE_VOIDP, TYPE_VOIDP], ['cb', 'data']], - parse_struct_signature('void (*cb)(const char*), const char* data')) - end - - def test_struct_string - assert_equal [[TYPE_INT,TYPE_VOIDP,TYPE_VOIDP], ['x', 'cb', 'name']], parse_struct_signature('int x; void (*cb)(); const char* name') - end - - def test_struct_bool - assert_equal([[TYPE_INT, TYPE_BOOL], ['x', 'toggle']], - parse_struct_signature('int x; bool toggle')) - end - - def test_struct_undefined - assert_raise(DLError) { parse_struct_signature(['int i', 'DWORD cb']) } - end - - def test_struct_undefined_with_type_alias - assert_equal [[TYPE_INT,-TYPE_LONG], ['i', 'cb']], parse_struct_signature(['int i', 'DWORD cb'], {"DWORD" => "unsigned long"}) - end - - def test_signature_basic - func, ret, args = parse_signature('void func()') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [], args - end - - def test_signature_semi - func, ret, args = parse_signature('void func();') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [], args - end - - def test_signature_void_arg - func, ret, args = parse_signature('void func(void)') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [], args - end - - def test_signature_type_args - types = [ - 'char', 'unsigned char', - 'short', 'unsigned short', - 'int', 'unsigned int', - 'long', 'unsigned long', - defined?(TYPE_LONG_LONG) && \ - [ - 'long long', 'unsigned long long', - ], - 'float', 'double', - 'const char*', 'void*', - ].flatten.compact - func, ret, args = parse_signature("void func(#{types.join(',')})") - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [ - TYPE_CHAR, -TYPE_CHAR, - TYPE_SHORT, -TYPE_SHORT, - TYPE_INT, -TYPE_INT, - TYPE_LONG, -TYPE_LONG, - defined?(TYPE_LONG_LONG) && \ - [ - TYPE_LONG_LONG, -TYPE_LONG_LONG, - ], - TYPE_FLOAT, TYPE_DOUBLE, - TYPE_VOIDP, TYPE_VOIDP, - ].flatten.compact, args - end - - def test_signature_single_variable - func, ret, args = parse_signature('void func(int x)') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [TYPE_INT], args - end - - def test_signature_multiple_variables - func, ret, args = parse_signature('void func(int x, const char* s)') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [TYPE_INT, TYPE_VOIDP], args - end - - def test_signature_array_variable - func, ret, args = parse_signature('void func(int x[], int y[40])') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [TYPE_VOIDP, TYPE_VOIDP], args - end - - def test_signature_function_pointer - func, ret, args = parse_signature('int func(int (*sum)(int x, int y), int x, int y)') - assert_equal 'func', func - assert_equal TYPE_INT, ret - assert_equal [TYPE_VOIDP, TYPE_INT, TYPE_INT], args - end - - def test_signature_variadic_arguments - unless Fiddle.const_defined?("TYPE_VARIADIC") - omit "libffi doesn't support variadic arguments" - end - assert_equal([ - "printf", - TYPE_INT, - [TYPE_VOIDP, TYPE_VARIADIC], - ], - parse_signature('int printf(const char *format, ...)')) - end - - def test_signature_return_pointer - func, ret, args = parse_signature('void* malloc(size_t)') - assert_equal 'malloc', func - assert_equal TYPE_VOIDP, ret - assert_equal [TYPE_SIZE_T], args - end - - def test_signature_return_array - func, ret, args = parse_signature('int (*func())[32]') - assert_equal 'func', func - assert_equal TYPE_VOIDP, ret - assert_equal [], args - end - - def test_signature_return_array_with_args - func, ret, args = parse_signature('int (*func(const char* s))[]') - assert_equal 'func', func - assert_equal TYPE_VOIDP, ret - assert_equal [TYPE_VOIDP], args - end - - def test_signature_return_function_pointer - func, ret, args = parse_signature('int (*func())(int x, int y)') - assert_equal 'func', func - assert_equal TYPE_VOIDP, ret - assert_equal [], args - end - - def test_signature_return_function_pointer_with_args - func, ret, args = parse_signature('int (*func(int z))(int x, int y)') - assert_equal 'func', func - assert_equal TYPE_VOIDP, ret - assert_equal [TYPE_INT], args - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_fiddle.rb b/test/fiddle/test_fiddle.rb deleted file mode 100644 index 69d0c3d179..0000000000 --- a/test/fiddle/test_fiddle.rb +++ /dev/null @@ -1,91 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -class TestFiddle < Fiddle::TestCase - def test_nil_true_etc - if ffi_backend? - omit("Fiddle::Q* aren't supported with FFI backend") - end - - assert_equal Fiddle::Qtrue, Fiddle.dlwrap(true) - assert_equal Fiddle::Qfalse, Fiddle.dlwrap(false) - assert_equal Fiddle::Qnil, Fiddle.dlwrap(nil) - assert Fiddle::Qundef - end - - def test_windows_constant - require 'rbconfig' - if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ - assert Fiddle::WINDOWS, "Fiddle::WINDOWS should be 'true' on Windows platforms" - else - refute Fiddle::WINDOWS, "Fiddle::WINDOWS should be 'false' on non-Windows platforms" - end - end - - def test_dlopen_linker_script_input_linux - omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux") - if Dir.glob("/usr/lib{,64}/**/libncurses.so").empty? - omit("libncurses.so is needed") - end - if ffi_backend? - omit("Fiddle::Handle#file_name doesn't exist in FFI backend") - end - - # libncurses.so uses INPUT() on Debian GNU/Linux and Arch Linux: - # - # Debian GNU/Linux: - # - # $ cat /usr/lib/x86_64-linux-gnu/libncurses.so - # INPUT(libncurses.so.6 -ltinfo) - # - # Arch Linux: - # $ cat /usr/lib/libncurses.so - # INPUT(-lncursesw) - handle = Fiddle.dlopen("libncurses.so") - begin - # /usr/lib/x86_64-linux-gnu/libncurses.so.6 -> - # libncurses.so.6 - normalized_file_name = File.basename(handle.file_name) - # libncurses.so.6 -> - # libncurses.so - # - # libncursesw.so -> - # libncursesw.so - normalized_file_name = normalized_file_name.sub(/\.so(\.\d+)+\z/, ".so") - # libncurses.so -> - # libncurses.so - # - # libncursesw.so -> - # libncurses.so - normalized_file_name = normalized_file_name.sub(/ncursesw/, "ncurses") - assert_equal("libncurses.so", normalized_file_name) - ensure - handle.close - end - end - - def test_dlopen_linker_script_group_linux - omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux") - if ffi_backend? - omit("Fiddle::Handle#file_name doesn't exist in FFI backend") - end - - # libc.so uses GROUP() on Debian GNU/Linux - # $ cat /usr/lib/x86_64-linux-gnu/libc.so - # /* GNU ld script - # Use the shared library, but some functions are only in - # the static library, so try that secondarily. */ - # OUTPUT_FORMAT(elf64-x86-64) - # GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) ) - handle = Fiddle.dlopen("libc.so") - begin - assert_equal("libc.so", - File.basename(handle.file_name, ".*")) - ensure - handle.close - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb deleted file mode 100644 index ca503f92ad..0000000000 --- a/test/fiddle/test_func.rb +++ /dev/null @@ -1,180 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestFunc < TestCase - def test_random - f = Function.new(@libc['srand'], [-TYPE_LONG], TYPE_VOID) - assert_nil f.call(10) - end - - def test_sinf - begin - f = Function.new(@libm['sinf'], [TYPE_FLOAT], TYPE_FLOAT) - rescue Fiddle::DLError - omit "libm may not have sinf()" - end - assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001 - end - - def test_sin - f = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE) - assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001 - end - - def test_string - if RUBY_ENGINE == "jruby" - omit("Function that returns string doesn't work with JRuby") - end - - under_gc_stress do - f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - buff = +"000" - str = f.call(buff, "123") - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - end - - def test_isdigit - f = Function.new(@libc['isdigit'], [TYPE_INT], TYPE_INT) - r1 = f.call(?1.ord) - r2 = f.call(?2.ord) - rr = f.call(?r.ord) - assert_operator r1, :>, 0 - assert_operator r2, :>, 0 - assert_equal 0, rr - end - - def test_atof - f = Function.new(@libc['atof'], [TYPE_VOIDP], TYPE_DOUBLE) - r = f.call("12.34") - assert_includes(12.00..13.00, r) - end - - def test_strtod - f = Function.new(@libc['strtod'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_DOUBLE) - buff1 = Pointer["12.34"] - buff2 = buff1 + 4 - r = f.call(buff1, - buff2) - assert_in_delta(12.34, r, 0.001) - end - - def test_qsort1 - if RUBY_ENGINE == "jruby" - omit("The untouched sanity check is broken on JRuby: https://github.com/jruby/jruby/issues/8365") - end - - closure_class = Class.new(Closure) do - def call(x, y) - Pointer.new(x)[0] <=> Pointer.new(y)[0] - end - end - - closure_class.create(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP]) do |callback| - qsort = Function.new(@libc['qsort'], - [TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T, TYPE_VOIDP], - TYPE_VOID) - untouched = "9341" - buff = +"9341" - qsort.call(buff, buff.size, 1, callback) - assert_equal("1349", buff) - - bug4929 = '[ruby-core:37395]' - buff = +"9341" - under_gc_stress do - qsort.call(buff, buff.size, 1, callback) - end - assert_equal("1349", buff, bug4929) - - # Ensure the test didn't mutate String literals - assert_equal("93" + "41", untouched) - end - ensure - # We can't use ObjectSpace with JRuby. - unless RUBY_ENGINE == "jruby" - # Ensure freeing all closures. - # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 . - not_freed_closures = [] - ObjectSpace.each_object(Fiddle::Closure) do |closure| - not_freed_closures << closure unless closure.freed? - end - assert_equal([], not_freed_closures) - end - end - - def test_snprintf - unless Fiddle.const_defined?("TYPE_VARIADIC") - omit "libffi doesn't support variadic arguments" - end - if Fiddle::WINDOWS - snprintf_name = "_snprintf" - else - snprintf_name = "snprintf" - end - begin - snprintf_pointer = @libc[snprintf_name] - rescue Fiddle::DLError - omit "Can't find #{snprintf_name}: #{$!.message}" - end - snprintf = Function.new(snprintf_pointer, - [ - :voidp, - :size_t, - :const_string, - :variadic, - ], - :int) - Pointer.malloc(1024, Fiddle::RUBY_FREE) do |output| - written = snprintf.call(output, - output.size, - "int: %d, string: %.*s, const string: %s\n", - :int, -29, - :int, 4, - :voidp, "Hello", - :const_string, "World") - assert_equal("int: -29, string: Hell, const string: World\n", - output[0, written]) - - string_like_class = Class.new do - def initialize(string) - @string = string - end - - def to_str - @string - end - end - written = snprintf.call(output, - output.size, - "string: %.*s, const string: %s, uint: %u\n", - :int, 2, - :voidp, "Hello", - :const_string, string_like_class.new("World"), - :int, 29) - assert_equal("string: He, const string: World, uint: 29\n", - output[0, written]) - end - end - - def test_rb_memory_view_available_p - omit "MemoryView is unavailable" unless defined? Fiddle::MemoryView - libruby = Fiddle.dlopen(nil) - case Fiddle::SIZEOF_VOIDP - when Fiddle::SIZEOF_LONG_LONG - value_type = -Fiddle::TYPE_LONG_LONG - else - value_type = -Fiddle::TYPE_LONG - end - rb_memory_view_available_p = - Function.new(libruby["rb_memory_view_available_p"], - [value_type], - :bool, - need_gvl: true) - assert_equal(false, rb_memory_view_available_p.call(Fiddle::Qnil)) - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb deleted file mode 100644 index ee5fdf30fb..0000000000 --- a/test/fiddle/test_function.rb +++ /dev/null @@ -1,316 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestFunction < Fiddle::TestCase - def setup - super - Fiddle.last_error = 0 - if WINDOWS - Fiddle.win32_last_error = nil - Fiddle.win32_last_socket_error = nil - end - end - - def teardown - # We can't use ObjectSpace with JRuby. - return if RUBY_ENGINE == "jruby" - # Ensure freeing all closures. - # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 . - not_freed_closures = [] - ObjectSpace.each_object(Fiddle::Closure) do |closure| - not_freed_closures << closure unless closure.freed? - end - assert_equal([], not_freed_closures) - end - - def test_default_abi - func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE) - assert_equal Function::DEFAULT, func.abi - end - - def test_name - func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE, name: 'sin') - assert_equal 'sin', func.name - end - - def test_name_symbol - func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE, name: :sin) - assert_equal :sin, func.name - end - - def test_need_gvl? - if RUBY_ENGINE == "jruby" - omit("rb_str_dup() doesn't exist in JRuby") - end - if RUBY_ENGINE == "truffleruby" - omit("rb_str_dup() doesn't work with TruffleRuby") - end - - libruby = Fiddle.dlopen(nil) - rb_str_dup = Function.new(libruby['rb_str_dup'], - [:voidp], - :voidp, - need_gvl: true) - assert(rb_str_dup.need_gvl?) - assert_equal('Hello', - Fiddle.dlunwrap(rb_str_dup.call(Fiddle.dlwrap('Hello')))) - end - - def test_argument_errors - assert_raise(TypeError) do - Function.new(@libm['sin'], TYPE_DOUBLE, TYPE_DOUBLE) - end - - assert_raise(TypeError) do - Function.new(@libm['sin'], ['foo'], TYPE_DOUBLE) - end - - assert_raise(TypeError) do - Function.new(@libm['sin'], [TYPE_DOUBLE], 'foo') - end - end - - def test_argument_type_conversion - type = Struct.new(:int, :call_count) do - def initialize(int) - super(int, 0) - end - def to_int - raise "exhausted" if (self.call_count += 1) > 1 - self.int - end - end - type_arg = type.new(TYPE_DOUBLE) - type_result = type.new(TYPE_DOUBLE) - assert_nothing_raised(RuntimeError) do - Function.new(@libm['sin'], [type_arg], type_result) - end - assert_equal(1, type_arg.call_count) - assert_equal(1, type_result.call_count) - end - - def test_call - func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE) - assert_in_delta 1.0, func.call(90 * Math::PI / 180), 0.0001 - end - - def test_integer_pointer_conversion - func = Function.new(@libc['memcpy'], [TYPE_VOIDP, TYPE_VOIDP, TYPE_SIZE_T], TYPE_VOIDP) - str = 'hello' - Pointer.malloc(str.bytesize, Fiddle::RUBY_FREE) do |dst| - func.call(dst.to_i, str, dst.size) - assert_equal(str, dst.to_str) - end - end - - def test_argument_count - closure_class = Class.new(Closure) do - def call one - 10 + one - end - end - closure_class.create(TYPE_INT, [TYPE_INT]) do |closure| - func = Function.new(closure, [TYPE_INT], TYPE_INT) - - assert_raise(ArgumentError) do - func.call(1,2,3) - end - assert_raise(ArgumentError) do - func.call - end - end - end - - def test_last_error - if RUBY_ENGINE == 'jruby' && WINDOWS - omit("Fiddle.last_error doesn't work well on JRuby on Windows") - end - - require 'rbconfig/sizeof' - - strtol = Function.new(@libc['strtol'], [TYPE_VOIDP, TYPE_VOIDP, TYPE_INT], TYPE_LONG) - - assert_equal 0, Fiddle.last_error - - assert_equal RbConfig::LIMITS["LONG_MAX"], strtol.call((2**128).to_s, nil, 10) # overflow - assert_equal Errno::ERANGE::Errno, Fiddle.last_error - - assert_equal 123, strtol.call("123", nil, 10) - refute_nil Fiddle.last_error - end - - if WINDOWS - def test_win32_last_error - kernel32 = Fiddle.dlopen("kernel32") - args = [kernel32["SetLastError"], [-TYPE_LONG], TYPE_VOID] - args << Function::STDCALL if Function.const_defined?(:STDCALL) - set_last_error = Function.new(*args) - assert_nil(Fiddle.win32_last_error) - n = 1 << 29 | 1 - set_last_error.call(n) - assert_equal(n, Fiddle.win32_last_error) - end - - def test_win32_last_socket_error - ws2_32 = Fiddle.dlopen("ws2_32") - args = [ws2_32["WSASetLastError"], [TYPE_INT], TYPE_VOID] - args << Function::STDCALL if Function.const_defined?(:STDCALL) - wsa_set_last_error = Function.new(*args) - assert_nil(Fiddle.win32_last_socket_error) - n = 1 << 29 | 1 - wsa_set_last_error.call(n) - assert_equal(n, Fiddle.win32_last_socket_error) - end - end - - def test_strcpy - if RUBY_ENGINE == "jruby" - omit("Function that returns string doesn't work with JRuby") - end - - f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - buff = +"000" - str = f.call(buff, "123") - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - - def call_proc(string_to_copy) - buff = +"000" - str = yield(buff, string_to_copy) - [buff, str] - end - - def test_function_as_proc - if RUBY_ENGINE == "jruby" - omit("Function that returns string doesn't work with JRuby") - end - - f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - buff, str = call_proc("123", &f) - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - - def test_function_as_method - if RUBY_ENGINE == "jruby" - omit("Function that returns string doesn't work with JRuby") - end - - f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - klass = Class.new do - define_singleton_method(:strcpy, &f) - end - buff = +"000" - str = klass.strcpy(buff, "123") - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - - def test_nogvl_poll - require "envutil" unless defined?(EnvUtil) - - # XXX hack to quiet down CI errors on EINTR from r64353 - # [ruby-core:88360] [Misc #14937] - # Making pipes (and sockets) non-blocking by default would allow - # us to get rid of POSIX timers / timer pthread - # https://bugs.ruby-lang.org/issues/14968 - IO.pipe { |r,w| IO.select([r], [w]) } - begin - poll = @libc['poll'] - rescue Fiddle::DLError - omit 'poll(2) not available' - end - f = Function.new(poll, [TYPE_VOIDP, TYPE_INT, TYPE_INT], TYPE_INT) - - msec = EnvUtil.apply_timeout_scale(1000) - t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - th = Thread.new { f.call(nil, 0, msec) } - n1 = f.call(nil, 0, msec) - n2 = th.value - t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - assert_in_delta(msec, t1 - t0, EnvUtil.apply_timeout_scale(500), 'slept amount of time') - assert_equal(0, n1, perror("poll(2) in main-thread")) - assert_equal(0, n2, perror("poll(2) in sub-thread")) - end - - def test_no_memory_leak - if RUBY_ENGINE == "jruby" - omit("rb_obj_frozen_p() doesn't exist in JRuby") - end - if RUBY_ENGINE == "truffleruby" - omit("memory leak detection is fragile with TruffleRuby") - end - - if respond_to?(:assert_nothing_leaked_memory) - rb_obj_frozen_p_symbol = Fiddle.dlopen(nil)["rb_obj_frozen_p"] - rb_obj_frozen_p = Fiddle::Function.new(rb_obj_frozen_p_symbol, - [Fiddle::TYPE_UINTPTR_T], - Fiddle::TYPE_UINTPTR_T) - a = "a" - n_tries = 100_000 - n_tries.times do - begin - a + 1 - rescue TypeError - end - end - n_arguments = 1 - sizeof_fiddle_generic = Fiddle::SIZEOF_VOIDP # Rough - size_per_try = - (sizeof_fiddle_generic * n_arguments) + - (Fiddle::SIZEOF_VOIDP * (n_arguments + 1)) - assert_nothing_leaked_memory(size_per_try * n_tries) do - n_tries.times do - begin - rb_obj_frozen_p.call(a) - rescue TypeError - end - end - end - else - prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_frozen_p"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"' - code = 'begin r.call(a); rescue TypeError; end' - assert_no_memory_leak(%w[-W0 -rfiddle], "#{prep}\n1000.times{#{code}}", "10_000.times {#{code}}", limit: 1.2) - end - end - - def test_ractor_shareable - omit("Need Ractor") unless defined?(Ractor) - assert_ractor_shareable(Function.new(@libm["sin"], - [TYPE_DOUBLE], - TYPE_DOUBLE)) - end - - def test_ractor_shareable_name - omit("Need Ractor") unless defined?(Ractor) - assert_ractor_shareable(Function.new(@libm["sin"], - [TYPE_DOUBLE], - TYPE_DOUBLE, - name: "sin")) - end - - def test_ractor_shareable_name_symbol - omit("Need Ractor") unless defined?(Ractor) - assert_ractor_shareable(Function.new(@libm["sin"], - [TYPE_DOUBLE], - TYPE_DOUBLE, - name: :sin)) - end - - private - - def perror(m) - proc do - if e = Fiddle.last_error - m = "#{m}: #{SystemCallError.new(e).message}" - end - m - end - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_handle.rb b/test/fiddle/test_handle.rb deleted file mode 100644 index ad8c45a00a..0000000000 --- a/test/fiddle/test_handle.rb +++ /dev/null @@ -1,244 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestHandle < TestCase - include Fiddle - - def test_library_unavailable - assert_raise(DLError) do - Fiddle::Handle.new("does-not-exist-library") - end - assert_raise(DLError) do - Fiddle::Handle.new("/does/not/exist/library.#{RbConfig::CONFIG['SOEXT']}") - end - end - - def test_to_i - if ffi_backend? - omit("Fiddle::Handle#to_i is unavailable with FFI backend") - end - - handle = Fiddle::Handle.new(LIBC_SO) - assert_kind_of Integer, handle.to_i - end - - def test_to_ptr - if ffi_backend? - omit("Fiddle::Handle#to_i is unavailable with FFI backend") - end - - handle = Fiddle::Handle.new(LIBC_SO) - ptr = handle.to_ptr - assert_equal ptr.to_i, handle.to_i - end - - def test_static_sym_unknown - assert_raise(DLError) { Fiddle::Handle.sym('fooo') } - assert_raise(DLError) { Fiddle::Handle['fooo'] } - refute Fiddle::Handle.sym_defined?('fooo') - end - - def test_static_sym - if ffi_backend? - omit("We can't assume static symbols with FFI backend") - end - - begin - # Linux / Darwin / FreeBSD - refute_nil Fiddle::Handle.sym('dlopen') - assert Fiddle::Handle.sym_defined?('dlopen') - assert_equal Fiddle::Handle.sym('dlopen'), Fiddle::Handle['dlopen'] - return - rescue - end - - begin - # NetBSD - require '-test-/dln/empty' - refute_nil Fiddle::Handle.sym('Init_empty') - assert_equal Fiddle::Handle.sym('Init_empty'), Fiddle::Handle['Init_empty'] - return - rescue - end - end unless /mswin|mingw/ =~ RUBY_PLATFORM - - def test_sym_closed_handle - handle = Fiddle::Handle.new(LIBC_SO) - handle.close - assert_raise(DLError) { handle.sym("calloc") } - assert_raise(DLError) { handle["calloc"] } - end - - def test_sym_unknown - handle = Fiddle::Handle.new(LIBC_SO) - assert_raise(DLError) { handle.sym('fooo') } - assert_raise(DLError) { handle['fooo'] } - refute handle.sym_defined?('fooo') - end - - def test_sym_with_bad_args - handle = Handle.new(LIBC_SO) - assert_raise(TypeError) { handle.sym(nil) } - assert_raise(TypeError) { handle[nil] } - end - - def test_sym - handle = Handle.new(LIBC_SO) - refute_nil handle.sym('calloc') - refute_nil handle['calloc'] - assert handle.sym_defined?('calloc') - end - - def test_handle_close - handle = Handle.new(LIBC_SO) - assert_equal 0, handle.close - end - - def test_handle_close_twice - handle = Handle.new(LIBC_SO) - handle.close - assert_raise(DLError) do - handle.close - end - end - - def test_dlopen_returns_handle - assert_instance_of Handle, dlopen(LIBC_SO) - end - - def test_initialize_noargs - if RUBY_ENGINE == "jruby" - omit("rb_str_new() doesn't exist in JRuby") - end - - handle = Handle.new - refute_nil handle['rb_str_new'] - end - - def test_initialize_flags - handle = Handle.new(LIBC_SO, RTLD_LAZY | RTLD_GLOBAL) - refute_nil handle['calloc'] - end - - def test_enable_close - handle = Handle.new(LIBC_SO) - assert !handle.close_enabled?, 'close is enabled' - - handle.enable_close - assert handle.close_enabled?, 'close is not enabled' - end - - def test_disable_close - handle = Handle.new(LIBC_SO) - - handle.enable_close - assert handle.close_enabled?, 'close is enabled' - handle.disable_close - assert !handle.close_enabled?, 'close is enabled' - end - - def test_file_name - if ffi_backend? - omit("Fiddle::Handle#file_name doesn't exist in FFI backend") - end - - file_name = Handle.new(LIBC_SO).file_name - if file_name - assert_kind_of String, file_name - expected = [File.basename(LIBC_SO)] - begin - expected << File.basename(File.realpath(LIBC_SO, File.dirname(file_name))) - rescue Errno::ENOENT - end - basename = File.basename(file_name) - unless File::FNM_SYSCASE.zero? - basename.downcase! - expected.each(&:downcase!) - end - assert_include expected, basename - end - end - - def test_NEXT - if ffi_backend? - omit("Fiddle::Handle::NEXT doesn't exist in FFI backend") - end - - begin - # Linux / Darwin - # - # There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT. The former will find - # the first occurrence of the desired symbol using the default library search order. The - # latter will find the next occurrence of a function in the search order after the current - # library. This allows one to provide a wrapper around a function in another shared - # library. - # --- Ubuntu Linux 8.04 dlsym(3) - handle = Handle::NEXT - refute_nil handle['malloc'] - return - rescue - end - - begin - # BSD - # - # If dlsym() is called with the special handle RTLD_NEXT, then the search - # for the symbol is limited to the shared objects which were loaded after - # the one issuing the call to dlsym(). Thus, if the function is called - # from the main program, all the shared libraries are searched. If it is - # called from a shared library, all subsequent shared libraries are - # searched. RTLD_NEXT is useful for implementing wrappers around library - # functions. For example, a wrapper function getpid() could access the - # "real" getpid() with dlsym(RTLD_NEXT, "getpid"). (Actually, the dlfunc() - # interface, below, should be used, since getpid() is a function and not a - # data object.) - # --- FreeBSD 8.0 dlsym(3) - require '-test-/dln/empty' - handle = Handle::NEXT - refute_nil handle['Init_empty'] - return - rescue - end - end unless /mswin|mingw/ =~ RUBY_PLATFORM - - def test_DEFAULT - if Fiddle::WINDOWS - omit("Fiddle::Handle::DEFAULT doesn't have malloc() on Windows") - end - - handle = Handle::DEFAULT - refute_nil handle['malloc'] - end - - def test_dlerror - # FreeBSD (at least 7.2 to 7.2) calls nsdispatch(3) when it calls - # getaddrinfo(3). And nsdispatch(3) doesn't call dlerror(3) even if - # it calls _nss_cache_cycle_prevention_function with dlsym(3). - # So our Fiddle::Handle#sym must call dlerror(3) before call dlsym. - # In general uses of dlerror(3) should call it before use it. - verbose, $VERBOSE = $VERBOSE, nil - require 'socket' - Socket.gethostbyname("localhost") - Fiddle.dlopen("/lib/libc.so.7").sym('strcpy') - ensure - $VERBOSE = verbose - end if /freebsd/=~ RUBY_PLATFORM - - if /cygwin|mingw|mswin/ =~ RUBY_PLATFORM - def test_fallback_to_ansi - k = Fiddle::Handle.new("kernel32.dll") - ansi = k["GetFileAttributesA"] - assert_equal(ansi, k["GetFileAttributes"], "should fallback to ANSI version") - end - end - - def test_ractor_shareable - omit("Need Ractor") unless defined?(Ractor) - assert_ractor_shareable(Fiddle::Handle.new(LIBC_SO)) - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_import.rb b/test/fiddle/test_import.rb deleted file mode 100644 index a6a3b66655..0000000000 --- a/test/fiddle/test_import.rb +++ /dev/null @@ -1,499 +0,0 @@ -# coding: US-ASCII -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/import' -rescue LoadError -end - -module Fiddle - module LIBC - extend Importer - dlload LIBC_SO, LIBM_SO - - typealias 'string', 'char*' - typealias 'FILE*', 'void*' - - extern "void *strcpy(char*, char*)" - extern "int isdigit(int)" - extern "double atof(string)" - extern "unsigned long strtoul(char*, char **, int)" - extern "int qsort(void*, unsigned long, unsigned long, void*)" - extern "int fprintf(FILE*, char*)" rescue nil - extern "int gettimeofday(timeval*, timezone*)" rescue nil - - Timeval = struct [ - "long tv_sec", - "long tv_usec", - ] - Timezone = struct [ - "int tz_minuteswest", - "int tz_dsttime", - ] - MyStruct = struct [ - "short num[5]", - "char c", - "unsigned char buff[7]", - ] - StructNestedStruct = struct [ - { - "vertices[2]" => { - position: ["float x", "float y", "float z"], - texcoord: ["float u", "float v"] - }, - object: ["int id", "void *user_data"], - }, - "int id" - ] - UnionNestedStruct = union [ - { - keyboard: [ - 'unsigned int state', - 'char key' - ], - mouse: [ - 'unsigned int button', - 'unsigned short x', - 'unsigned short y' - ] - } - ] - end - - class TestImport < TestCase - def test_ensure_call_dlload - err = assert_raise(RuntimeError) do - Class.new do - extend Importer - extern "void *strcpy(char*, char*)" - end - end - assert_match(/call dlload before/, err.message) - end - - def test_struct_memory_access() - # check memory operations performed directly on struct - Fiddle::Importer.struct(['int id']).malloc(Fiddle::RUBY_FREE) do |my_struct| - my_struct[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT - assert_equal 0x01010101, my_struct.id - - my_struct.id = 0 - assert_equal "\x00".b * Fiddle::SIZEOF_INT, my_struct[0, Fiddle::SIZEOF_INT] - end - end - - def test_struct_ptr_array_subscript_multiarg() - # check memory operations performed on struct#to_ptr - Fiddle::Importer.struct([ 'int x' ]).malloc(Fiddle::RUBY_FREE) do |struct| - ptr = struct.to_ptr - - struct.x = 0x02020202 - assert_equal("\x02".b * Fiddle::SIZEOF_INT, ptr[0, Fiddle::SIZEOF_INT]) - - ptr[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT - assert_equal 0x01010101, struct.x - end - end - - def test_malloc() - LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s1| - LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s2| - refute_equal(s1.to_ptr.to_i, s2.to_ptr.to_i) - end - end - end - - def test_sizeof() - assert_equal(SIZEOF_VOIDP, LIBC.sizeof("FILE*")) - assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(LIBC::MyStruct)) - LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |my_struct| - assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(my_struct)) - end - assert_equal(SIZEOF_LONG_LONG, LIBC.sizeof("long long")) if defined?(SIZEOF_LONG_LONG) - assert_equal(LIBC::StructNestedStruct.size(), LIBC.sizeof(LIBC::StructNestedStruct)) - end - - Fiddle.constants.grep(/\ATYPE_(?!VOID|VARIADIC\z)(.*)/) do - type = $& - const_type_name = $1 - size = Fiddle.const_get("SIZEOF_#{const_type_name}") - if const_type_name == "CONST_STRING" - name = "const_string" - type_name = "const char*" - else - name = $1.sub(/P\z/,"*").gsub(/_(?!T\z)/, " ").downcase - type_name = name - end - type_name = "unsigned #{$1}" if type_name =~ /\Au(long|short|char|int|long long)\z/ - - define_method("test_sizeof_#{name}") do - assert_equal(size, Fiddle::Importer.sizeof(type_name), type) - end - end - - # Assert that the unsigned constants are equal to the "negative" signed ones - # for backwards compatibility - def test_unsigned_equals_negative_signed - Fiddle.constants.grep(/\ATYPE_(?!VOID|VARIADIC\z)(U.*)/) do |unsigned| - assert_equal(-Fiddle.const_get(unsigned.to_s.sub(/U/, '')), - Fiddle.const_get(unsigned)) - end - end - - def test_type_constants - Fiddle::Types.constants.each do |const| - assert_equal Fiddle::Types.const_get(const), Fiddle.const_get("TYPE_#{const}") - end - end - - def test_unsigned_result() - d = (2 ** 31) + 1 - - r = LIBC.strtoul(d.to_s, nil, 0) - assert_equal(d, r) - end - - def test_io() - if ffi_backend? - omit("BUILD_RUBY_PLATFORM doesn't exist in FFI backend") - end - - if( RUBY_PLATFORM != BUILD_RUBY_PLATFORM ) || !defined?(LIBC.fprintf) - return - end - io_in,io_out = IO.pipe() - LIBC.fprintf(io_out, "hello") - io_out.flush() - io_out.close() - str = io_in.read() - io_in.close() - assert_equal("hello", str) - end - - def test_value() - i = LIBC.value('int', 2) - assert_equal(2, i.value) - - d = LIBC.value('double', 2.0) - assert_equal(2.0, d.value) - - ary = LIBC.value('int[3]', [0,1,2]) - assert_equal([0,1,2], ary.value) - end - - def test_struct_array_assignment() - Fiddle::Importer.struct(["unsigned int stages[3]"]).malloc(Fiddle::RUBY_FREE) do |instance| - instance.stages[0] = 1024 - instance.stages[1] = 10 - instance.stages[2] = 100 - assert_equal 1024, instance.stages[0] - assert_equal 10, instance.stages[1] - assert_equal 100, instance.stages[2] - assert_equal [1024, 10, 100].pack(Fiddle::PackInfo::PACK_MAP[-Fiddle::TYPE_INT] * 3), - instance.to_ptr[0, 3 * Fiddle::SIZEOF_INT] - assert_raise(IndexError) { instance.stages[-1] = 5 } - assert_raise(IndexError) { instance.stages[3] = 5 } - end - end - - def test_nested_struct_reusing_other_structs() - position_struct = Fiddle::Importer.struct(['float x', 'float y', 'float z']) - texcoord_struct = Fiddle::Importer.struct(['float u', 'float v']) - vertex_struct = Fiddle::Importer.struct(position: position_struct, texcoord: texcoord_struct) - mesh_struct = Fiddle::Importer.struct([ - { - "vertices[2]" => vertex_struct, - object: [ - "int id", - "void *user_data", - ], - }, - "int id", - ]) - assert_equal LIBC::StructNestedStruct.size, mesh_struct.size - - - keyboard_event_struct = Fiddle::Importer.struct(['unsigned int state', 'char key']) - mouse_event_struct = Fiddle::Importer.struct(['unsigned int button', 'unsigned short x', 'unsigned short y']) - event_union = Fiddle::Importer.union([{ keyboard: keyboard_event_struct, mouse: mouse_event_struct}]) - assert_equal LIBC::UnionNestedStruct.size, event_union.size - end - - def test_nested_struct_alignment_is_not_its_size() - inner = Fiddle::Importer.struct(['int x', 'int y', 'int z', 'int w']) - outer = Fiddle::Importer.struct(['char a', { 'nested' => inner }, 'char b']) - outer.malloc(Fiddle::RUBY_FREE) do |instance| - offset = instance.to_ptr.instance_variable_get(:"@offset") - assert_equal Fiddle::SIZEOF_INT * 5, offset.last - assert_equal Fiddle::SIZEOF_INT * 6, outer.size - assert_equal instance.to_ptr.size, outer.size - end - end - - def test_struct_nested_struct_members() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - Fiddle::Pointer.malloc(24, Fiddle::RUBY_FREE) do |user_data| - s.vertices[0].position.x = 1 - s.vertices[0].position.y = 2 - s.vertices[0].position.z = 3 - s.vertices[0].texcoord.u = 4 - s.vertices[0].texcoord.v = 5 - s.vertices[1].position.x = 6 - s.vertices[1].position.y = 7 - s.vertices[1].position.z = 8 - s.vertices[1].texcoord.u = 9 - s.vertices[1].texcoord.v = 10 - s.object.id = 100 - s.object.user_data = user_data - s.id = 101 - assert_equal({ - "vertices" => [ - { - "position" => { - "x" => 1, - "y" => 2, - "z" => 3, - }, - "texcoord" => { - "u" => 4, - "v" => 5, - }, - }, - { - "position" => { - "x" => 6, - "y" => 7, - "z" => 8, - }, - "texcoord" => { - "u" => 9, - "v" => 10, - }, - }, - ], - "object" => { - "id" => 100, - "user_data" => user_data, - }, - "id" => 101, - }, - s.to_h) - end - end - end - - def test_union_nested_struct_members() - LIBC::UnionNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.keyboard.state = 100 - s.keyboard.key = 101 - assert_equal(100, s.mouse.button) - refute_equal( 0, s.mouse.x) - end - end - - def test_struct_nested_struct_replace_array_element() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.vertices[0].position.x = 5 - - vertex_struct = Fiddle::Importer.struct [{ - position: ["float x", "float y", "float z"], - texcoord: ["float u", "float v"] - }] - vertex_struct.malloc(Fiddle::RUBY_FREE) do |vertex| - vertex.position.x = 100 - s.vertices[0] = vertex - - # make sure element was copied by value, but things like memory address - # should not be changed - assert_equal(100, s.vertices[0].position.x) - refute_equal(vertex.object_id, s.vertices[0].object_id) - refute_equal(vertex.to_ptr, s.vertices[0].to_ptr) - end - end - end - - def test_struct_nested_struct_replace_array_element_nil() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.vertices[0].position.x = 5 - s.vertices[0] = nil - assert_equal({ - "position" => { - "x" => 0.0, - "y" => 0.0, - "z" => 0.0, - }, - "texcoord" => { - "u" => 0.0, - "v" => 0.0, - }, - }, - s.vertices[0].to_h) - end - end - - def test_struct_nested_struct_replace_array_element_hash() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.vertices[0] = nil - s.vertices[0] = { - position: { - x: 10, - y: 100, - }, - } - assert_equal({ - "position" => { - "x" => 10.0, - "y" => 100.0, - "z" => 0.0, - }, - "texcoord" => { - "u" => 0.0, - "v" => 0.0, - }, - }, - s.vertices[0].to_h) - end - end - - def test_struct_nested_struct_replace_entire_array() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - vertex_struct = Fiddle::Importer.struct [{ - position: ["float x", "float y", "float z"], - texcoord: ["float u", "float v"] - }] - - vertex_struct.malloc(Fiddle::RUBY_FREE) do |same0| - vertex_struct.malloc(Fiddle::RUBY_FREE) do |same1| - same = [same0, same1] - same[0].position.x = 1; same[1].position.x = 6 - same[0].position.y = 2; same[1].position.y = 7 - same[0].position.z = 3; same[1].position.z = 8 - same[0].texcoord.u = 4; same[1].texcoord.u = 9 - same[0].texcoord.v = 5; same[1].texcoord.v = 10 - s.vertices = same - assert_equal([ - { - "position" => { - "x" => 1.0, - "y" => 2.0, - "z" => 3.0, - }, - "texcoord" => { - "u" => 4.0, - "v" => 5.0, - }, - }, - { - "position" => { - "x" => 6.0, - "y" => 7.0, - "z" => 8.0, - }, - "texcoord" => { - "u" => 9.0, - "v" => 10.0, - }, - } - ], - s.vertices.collect(&:to_h)) - end - end - end - end - - def test_struct_nested_struct_replace_entire_array_with_different_struct() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - different_struct_same_size = Fiddle::Importer.struct [{ - a: ['float i', 'float j', 'float k'], - b: ['float l', 'float m'] - }] - - different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different0| - different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different1| - different = [different0, different1] - different[0].a.i = 11; different[1].a.i = 16 - different[0].a.j = 12; different[1].a.j = 17 - different[0].a.k = 13; different[1].a.k = 18 - different[0].b.l = 14; different[1].b.l = 19 - different[0].b.m = 15; different[1].b.m = 20 - s.vertices[0][0, s.vertices[0].class.size] = different[0].to_ptr - s.vertices[1][0, s.vertices[1].class.size] = different[1].to_ptr - assert_equal([ - { - "position" => { - "x" => 11.0, - "y" => 12.0, - "z" => 13.0, - }, - "texcoord" => { - "u" => 14.0, - "v" => 15.0, - }, - }, - { - "position" => { - "x" => 16.0, - "y" => 17.0, - "z" => 18.0, - }, - "texcoord" => { - "u" => 19.0, - "v" => 20.0, - }, - } - ], - s.vertices.collect(&:to_h)) - end - end - end - end - - def test_struct() - LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.num = [0,1,2,3,4] - s.c = ?a.ord - s.buff = "012345\377" - assert_equal([0,1,2,3,4], s.num) - assert_equal(?a.ord, s.c) - assert_equal([?0.ord,?1.ord,?2.ord,?3.ord,?4.ord,?5.ord,"\xFF".ord], s.buff) - end - end - - def test_gettimeofday() - if( defined?(LIBC.gettimeofday) ) - LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |timeval| - LIBC::Timezone.malloc(Fiddle::RUBY_FREE) do |timezone| - LIBC.gettimeofday(timeval, timezone) - end - cur = Time.now() - assert(cur.to_i - 2 <= timeval.tv_sec && timeval.tv_sec <= cur.to_i) - end - end - end - - def test_strcpy() - if RUBY_ENGINE == "jruby" - omit("Function that returns string doesn't work with JRuby") - end - - buff = +"000" - str = LIBC.strcpy(buff, "123") - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - - def test_isdigit - r1 = LIBC.isdigit(?1.ord) - r2 = LIBC.isdigit(?2.ord) - rr = LIBC.isdigit(?r.ord) - assert_operator(r1, :>, 0) - assert_operator(r2, :>, 0) - assert_equal(0, rr) - end - - def test_atof - r = LIBC.atof("12.34") - assert_includes(12.00..13.00, r) - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_memory_view.rb b/test/fiddle/test_memory_view.rb deleted file mode 100644 index da00d66c91..0000000000 --- a/test/fiddle/test_memory_view.rb +++ /dev/null @@ -1,175 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError - return -end - -begin - require '-test-/memory_view' -rescue LoadError - return -end - -module Fiddle - class TestMemoryView < TestCase - def setup - omit "MemoryView is unavailable" unless defined? Fiddle::MemoryView - end - - def test_null_ptr - assert_raise(ArgumentError) do - MemoryView.new(Fiddle::NULL) - end - end - - def test_memory_view_from_unsupported_obj - obj = Object.new - assert_raise(ArgumentError) do - MemoryView.new(obj) - end - end - - def test_memory_view_from_pointer - str = Marshal.load(Marshal.dump("hello world")) - ptr = Pointer[str] - mview = MemoryView.new(ptr) - begin - assert_same(ptr, mview.obj) - assert_equal(str.bytesize, mview.byte_size) - assert_equal(true, mview.readonly?) - assert_equal(nil, mview.format) - assert_equal(1, mview.item_size) - assert_equal(1, mview.ndim) - assert_equal(nil, mview.shape) - assert_equal(nil, mview.strides) - assert_equal(nil, mview.sub_offsets) - - codes = str.codepoints - assert_equal(codes, (0...str.bytesize).map {|i| mview[i] }) - ensure - mview.release - end - end - - def test_memory_view_multi_dimensional - omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils - - buf = [ 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 10, 11, 12 ].pack("l!*") - shape = [3, 4] - md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, nil) - mview = Fiddle::MemoryView.new(md) - begin - assert_equal(buf.bytesize, mview.byte_size) - assert_equal("l!", mview.format) - assert_equal(Fiddle::SIZEOF_LONG, mview.item_size) - assert_equal(2, mview.ndim) - assert_equal(shape, mview.shape) - assert_equal([Fiddle::SIZEOF_LONG*4, Fiddle::SIZEOF_LONG], mview.strides) - assert_equal(nil, mview.sub_offsets) - assert_equal(1, mview[0, 0]) - assert_equal(4, mview[0, 3]) - assert_equal(6, mview[1, 1]) - assert_equal(10, mview[2, 1]) - ensure - mview.release - end - end - - def test_memory_view_multi_dimensional_with_strides - omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils - - buf = [ 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16 ].pack("l!*") - shape = [2, 8] - strides = [4*Fiddle::SIZEOF_LONG*2, Fiddle::SIZEOF_LONG*2] - md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, strides) - mview = Fiddle::MemoryView.new(md) - begin - assert_equal("l!", mview.format) - assert_equal(Fiddle::SIZEOF_LONG, mview.item_size) - assert_equal(buf.bytesize, mview.byte_size) - assert_equal(2, mview.ndim) - assert_equal(shape, mview.shape) - assert_equal(strides, mview.strides) - assert_equal(nil, mview.sub_offsets) - assert_equal(1, mview[0, 0]) - assert_equal(5, mview[0, 2]) - assert_equal(9, mview[1, 0]) - assert_equal(15, mview[1, 3]) - ensure - mview.release - end - end - - def test_memory_view_multi_dimensional_with_multiple_members - omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils - - buf = [ 1, 2, 3, 4, 5, 6, 7, 8, - -1, -2, -3, -4, -5, -6, -7, -8].pack("s*") - shape = [2, 4] - strides = [4*Fiddle::SIZEOF_SHORT*2, Fiddle::SIZEOF_SHORT*2] - md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides) - mview = Fiddle::MemoryView.new(md) - begin - assert_equal("ss", mview.format) - assert_equal(Fiddle::SIZEOF_SHORT*2, mview.item_size) - assert_equal(buf.bytesize, mview.byte_size) - assert_equal(2, mview.ndim) - assert_equal(shape, mview.shape) - assert_equal(strides, mview.strides) - assert_equal(nil, mview.sub_offsets) - assert_equal([1, 2], mview[0, 0]) - assert_equal([5, 6], mview[0, 2]) - assert_equal([-1, -2], mview[1, 0]) - assert_equal([-7, -8], mview[1, 3]) - ensure - mview.release - end - end - - def test_export - str = "hello world" - mview_str = MemoryView.export(Pointer[str]) do |mview| - mview.to_s - end - assert_equal(str, mview_str) - end - - def test_release - ptr = Pointer["hello world"] - mview = MemoryView.new(ptr) - assert_same(ptr, mview.obj) - mview.release - assert_nil(mview.obj) - end - - def test_to_s - # U+3042 HIRAGANA LETTER A - data = "\u{3042}" - ptr = Pointer[data] - mview = MemoryView.new(ptr) - begin - string = mview.to_s - assert_equal([data.b, true], - [string, string.frozen?]) - ensure - mview.release - end - end - - def test_ractor_shareable - omit("Need Ractor") unless defined?(Ractor) - ptr = Pointer["hello world"] - mview = MemoryView.new(ptr) - begin - assert_ractor_shareable(mview) - assert_predicate(ptr, :frozen?) - ensure - mview.release - end - end - end -end diff --git a/test/fiddle/test_pack.rb b/test/fiddle/test_pack.rb deleted file mode 100644 index ade1dd5040..0000000000 --- a/test/fiddle/test_pack.rb +++ /dev/null @@ -1,37 +0,0 @@ -begin - require_relative 'helper' - require 'fiddle/pack' -rescue LoadError - return -end - -module Fiddle - class TestPack < TestCase - def test_pack_map - if defined?(TYPE_LONG_LONG) - assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG_LONG]) - end - - case Fiddle::SIZEOF_VOIDP - when 8 - assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[TYPE_VOIDP]).unpack(PackInfo::PACK_MAP[TYPE_VOIDP]) - when 4 - assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[TYPE_VOIDP]).unpack(PackInfo::PACK_MAP[TYPE_VOIDP]) - end - - case Fiddle::SIZEOF_LONG - when 8 - assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG]) - when 4 - assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG]) - end - - if Fiddle::SIZEOF_INT == 4 - assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_INT]).unpack(PackInfo::PACK_MAP[-TYPE_INT]) - end - - assert_equal [0xffff], [0xffff].pack(PackInfo::PACK_MAP[-TYPE_SHORT]).unpack(PackInfo::PACK_MAP[-TYPE_SHORT]) - assert_equal [0xff], [0xff].pack(PackInfo::PACK_MAP[-TYPE_CHAR]).unpack(PackInfo::PACK_MAP[-TYPE_CHAR]) - end - end -end diff --git a/test/fiddle/test_pinned.rb b/test/fiddle/test_pinned.rb deleted file mode 100644 index ad132579b0..0000000000 --- a/test/fiddle/test_pinned.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError - return -end - -module Fiddle - class TestPinned < Fiddle::TestCase - def test_pin_object - x = Object.new - pinner = Pinned.new x - assert_same x, pinner.ref - end - - def test_clear - pinner = Pinned.new Object.new - refute pinner.cleared? - pinner.clear - assert pinner.cleared? - ex = assert_raise(Fiddle::ClearedReferenceError) do - pinner.ref - end - assert_match "called on", ex.message - end - - def test_ractor_shareable - omit("Need Ractor") unless defined?(Ractor) - obj = Object.new - assert_ractor_shareable(Pinned.new(obj)) - assert_predicate(obj, :frozen?) - end - end -end diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb deleted file mode 100644 index 9d490f9f26..0000000000 --- a/test/fiddle/test_pointer.rb +++ /dev/null @@ -1,319 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestPointer < TestCase - def dlwrap arg - Fiddle.dlwrap arg - end - - def test_can_read_write_memory - # Allocate some memory - Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP, Fiddle::RUBY_FREE) do |pointer| - address = pointer.to_i - bytes_to_write = Fiddle::SIZEOF_VOIDP.times.to_a.pack("C*") - - # Write to the memory - Fiddle::Pointer.write(address, bytes_to_write) - - # Read the bytes out again - bytes = Fiddle::Pointer.read(address, Fiddle::SIZEOF_VOIDP) - assert_equal bytes_to_write, bytes - end - end - - def test_cptr_to_int - null = Fiddle::NULL - assert_equal(null.to_i, null.to_int) - end - - def test_malloc_free_func_int - free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID) - assert_equal free.to_i, Fiddle::RUBY_FREE.to_i - - ptr = Pointer.malloc(10, free.to_i) - assert_equal 10, ptr.size - assert_equal free.to_i, ptr.free.to_i - end - - def test_malloc_free_func - free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID) - - ptr = Pointer.malloc(10, free) - assert_equal 10, ptr.size - assert_equal free.to_i, ptr.free.to_i - end - - def test_malloc_block - escaped_ptr = nil - returned = Pointer.malloc(10, Fiddle::RUBY_FREE) do |ptr| - assert_equal 10, ptr.size - assert_equal Fiddle::RUBY_FREE, ptr.free.to_i - escaped_ptr = ptr - :returned - end - assert_equal :returned, returned - assert escaped_ptr.freed? - end - - def test_malloc_block_no_free - assert_raise ArgumentError do - Pointer.malloc(10) { |ptr| } - end - end - - def test_malloc_subclass - subclass = Class.new(Pointer) - subclass.malloc(10, Fiddle::RUBY_FREE) do |ptr| - assert ptr.is_a?(subclass) - end - end - - def test_to_str - str = Marshal.load(Marshal.dump("hello world")) - ptr = Pointer[str] - - assert_equal 3, ptr.to_str(3).length - assert_equal str, ptr.to_str - - ptr[5] = 0 - assert_equal "hello\0world", ptr.to_str - end - - def test_to_s - str = Marshal.load(Marshal.dump("hello world")) - ptr = Pointer[str] - - assert_equal 3, ptr.to_s(3).length - assert_equal str, ptr.to_s - - ptr[5] = 0 - assert_equal 'hello', ptr.to_s - end - - def test_minus - str = "hello world" - ptr = Pointer[str] - assert_equal ptr.to_s, (ptr + 3 - 3).to_s - end - - # TODO: what if the pointer size is 0? raise an exception? do we care? - def test_plus - str = "hello world" - ptr = Pointer[str] - new_str = ptr + 3 - assert_equal 'lo world', new_str.to_s - end - - def test_inspect - if ffi_backend? - omit("Fiddle::Pointer#inspect is incompatible with FFI backend") - end - - ptr = Pointer.new(0) - inspect = ptr.inspect - assert_match(/size=#{ptr.size}/, inspect) - assert_match(/free=#{sprintf("%#x", ptr.free.to_i)}/, inspect) - assert_match(/ptr=#{sprintf("%#x", ptr.to_i)}/, inspect) - end - - def test_to_ptr_string - str = "hello world" - ptr = Pointer[str] - assert_equal str.length, ptr.size - assert_equal 'hello', ptr[0,5] - end - - def test_to_ptr_io - if ffi_backend? - omit("Fiddle::Pointer.to_ptr(IO) isn't supported with FFI backend") - end - - Pointer.malloc(10, Fiddle::RUBY_FREE) do |buf| - File.open(__FILE__, 'r') do |f| - ptr = Pointer.to_ptr f - fread = Function.new(@libc['fread'], - [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP], - TYPE_INT) - fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i) - end - - File.open(__FILE__, 'r') do |f| - assert_equal f.read(9), buf.to_s - end - end - end - - def test_to_ptr_with_ptr - ptr = Pointer.new 0 - ptr2 = Pointer.to_ptr Struct.new(:to_ptr).new(ptr) - assert_equal ptr, ptr2 - - assert_raise(Fiddle::DLError) do - Pointer.to_ptr Struct.new(:to_ptr).new(nil) - end - end - - def test_to_ptr_with_int - ptr = Pointer.new 0 - assert_equal ptr, Pointer[0] - end - - MimicInteger = Struct.new(:to_int) - def test_to_ptr_with_to_int - ptr = Pointer.new 0 - assert_equal ptr, Pointer[MimicInteger.new(0)] - end - - def test_equals - ptr = Pointer.new 0 - ptr2 = Pointer.new 0 - assert_equal ptr2, ptr - end - - def test_not_equals - ptr = Pointer.new 0 - refute_equal 10, ptr, '10 should not equal the pointer' - end - - def test_cmp - ptr = Pointer.new 0 - assert_nil(ptr <=> 10, '10 should not be comparable') - end - - def test_ref_ptr - if ffi_backend? - omit("Fiddle.dlwrap([]) isn't supported with FFI backend") - end - - ary = [0,1,2,4,5] - addr = Pointer.new(dlwrap(ary)) - assert_equal addr.to_i, addr.ref.ptr.to_i - - assert_equal addr.to_i, (+ (- addr)).to_i - end - - def test_to_value - if ffi_backend? - omit("Fiddle.dlwrap([]) isn't supported with FFI backend") - end - - ary = [0,1,2,4,5] - addr = Pointer.new(dlwrap(ary)) - assert_equal ary, addr.to_value - end - - def test_free - ptr = Pointer.malloc(4) - begin - assert_nil ptr.free - ensure - Fiddle.free ptr - end - end - - def test_free= - free = Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID) - ptr = Pointer.malloc(4) - ptr.free = free - - assert_equal free.ptr, ptr.free.ptr - end - - def test_free_with_func - ptr = Pointer.malloc(4, Fiddle::RUBY_FREE) - refute ptr.freed? - ptr.call_free - assert ptr.freed? - ptr.call_free # you can safely run it again - assert ptr.freed? - GC.start # you can safely run the GC routine - assert ptr.freed? - end - - def test_free_with_no_func - ptr = Pointer.malloc(4) - refute ptr.freed? - ptr.call_free - refute ptr.freed? - ptr.call_free # you can safely run it again - refute ptr.freed? - end - - def test_freed? - ptr = Pointer.malloc(4, Fiddle::RUBY_FREE) - refute ptr.freed? - ptr.call_free - assert ptr.freed? - end - - def test_null? - ptr = Pointer.new(0) - assert ptr.null? - end - - def test_size - Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr| - assert_equal 4, ptr.size - end - end - - def test_size= - Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr| - ptr.size = 10 - assert_equal 10, ptr.size - end - end - - def test_aref_aset - check = Proc.new{|str,ptr| - assert_equal(str.size(), ptr.size()) - assert_equal(str, ptr.to_s()) - assert_equal(str[0,2], ptr.to_s(2)) - assert_equal(str[0,2], ptr[0,2]) - assert_equal(str[1,2], ptr[1,2]) - assert_equal(str[1,0], ptr[1,0]) - assert_equal(str[0].ord, ptr[0]) - assert_equal(str[1].ord, ptr[1]) - } - str = Marshal.load(Marshal.dump('abc')) - ptr = Pointer[str] - check.call(str, ptr) - - str[0] = "c" - assert_equal 'c'.ord, ptr[0] = "c".ord - check.call(str, ptr) - - str[0,2] = "aa" - assert_equal 'aa', ptr[0,2] = "aa" - check.call(str, ptr) - - ptr2 = Pointer['cdeeee'] - str[0,2] = "cd" - assert_equal ptr2, ptr[0,2] = ptr2 - check.call(str, ptr) - - ptr3 = Pointer['vvvv'] - str[0,2] = "vv" - assert_equal ptr3.to_i, ptr[0,2] = ptr3.to_i - check.call(str, ptr) - end - - def test_null_pointer - nullpo = Pointer.new(0) - assert_raise(DLError) {nullpo[0]} - assert_raise(DLError) {nullpo[0] = 1} - end - - def test_ractor_shareable - omit("Need Ractor") unless defined?(Ractor) - assert_ractor_shareable(Fiddle::NULL) - ary = [0, 1, 2, 4, 5] - addr = Pointer.new(dlwrap(ary)) - assert_ractor_shareable(addr) - end - end -end if defined?(Fiddle) |