diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c index 19bdd8a896..27b703df9e 100644 --- a/ext/fiddle/conversions.c +++ b/ext/fiddle/conversions.c @@ -1,5 +1,113 @@ #include +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 + 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; + 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 + 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"); + 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 + 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 { + type = original_type; + } + } + + return rb_to_int(type); +} + ffi_type * rb_fiddle_int_to_ffi_type(int type) { diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h index f900efa9ad..1de956e90c 100644 --- a/ext/fiddle/conversions.h +++ b/ext/fiddle/conversions.h @@ -25,6 +25,7 @@ typedef union } fiddle_generic; /* Deprecated. Use rb_fiddle_*() version. */ +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); diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c index be287e6fdb..e6435ba3f3 100644 --- a/ext/fiddle/fiddle.c +++ b/ext/fiddle/fiddle.c @@ -3,38 +3,6 @@ VALUE mFiddle; VALUE rb_eFiddleError; -#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) - void Init_fiddle_pointer(void); /* diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h index f142229b0c..16f12cab74 100644 --- a/ext/fiddle/fiddle.h +++ b/ext/fiddle/fiddle.h @@ -118,6 +118,38 @@ #define TYPE_VARIADIC 9 #define TYPE_CONST_STRING 10 +#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) + #define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x) #define ALIGN_VOIDP ALIGN_OF(void*) diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c index 8771dd3e30..437dbb624a 100644 --- a/ext/fiddle/function.c +++ b/ext/fiddle/function.c @@ -106,7 +106,9 @@ normalize_argument_types(const char *name, 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 = NUM2INT(arg_type); + 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, @@ -146,6 +148,7 @@ initialize(int argc, VALUE argv[], VALUE self) 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); @@ -256,7 +259,9 @@ function_call(int argc, VALUE argv[], VALUE self) 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 = NUM2INT(arg_type); + 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)); } diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb index ca9d4ccb34..d3604c79c3 100644 --- a/test/fiddle/test_func.rb +++ b/test/fiddle/test_func.rb @@ -96,22 +96,22 @@ module Fiddle end snprintf = Function.new(snprintf_pointer, [ - TYPE_VOIDP, - TYPE_SIZE_T, - TYPE_CONST_STRING, - TYPE_VARIADIC, + :voidp, + :size_t, + :const_string, + :variadic, ], - TYPE_INT) + :int) output_buffer = " " * 1024 output = Pointer[output_buffer] written = snprintf.call(output, output.size, "int: %d, string: %.*s, const string: %s\n", - TYPE_INT, -29, - TYPE_INT, 4, - TYPE_VOIDP, "Hello", - TYPE_CONST_STRING, "World") + :int, -29, + :int, 4, + :voidp, "Hello", + :const_string, "World") assert_equal("int: -29, string: Hell, const string: World\n", output_buffer[0, written]) @@ -127,10 +127,10 @@ module Fiddle written = snprintf.call(output, output.size, "string: %.*s, const string: %s, uint: %u\n", - TYPE_INT, 2, - TYPE_VOIDP, "Hello", - TYPE_CONST_STRING, string_like_class.new("World"), - TYPE_INT, 29) + :int, 2, + :voidp, "Hello", + :const_string, string_like_class.new("World"), + :int, 29) assert_equal("string: He, const string: World, uint: 29\n", output_buffer[0, written]) end