diff options
author | Sutou Kouhei <[email protected]> | 2023-10-28 06:11:30 +0900 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2023-11-08 09:25:44 +0900 |
commit | 2a6d6d3d65de43635a5f6ad38dbca170f1e40119 (patch) | |
tree | 097aff88d59c4e7329138d98408ff706846f28fe | |
parent | d30ea5831e0aedada3362a2d268e7bc836b93f27 (diff) |
[ruby/fiddle] Use Ruby's true/false for C bool
GitHub: fix https://github.com/ruby/fiddle/pull/130
Reported by Benoit Daloze. Thanks!!!
https://github.com/ruby/fiddle/commit/2640e0148e
-rw-r--r-- | ext/fiddle/closure.c | 21 | ||||
-rw-r--r-- | ext/fiddle/conversions.c | 64 | ||||
-rw-r--r-- | ext/fiddle/conversions.h | 3 | ||||
-rw-r--r-- | ext/fiddle/fiddle.c | 8 | ||||
-rw-r--r-- | ext/fiddle/fiddle.h | 1 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/import.rb | 2 | ||||
-rw-r--r-- | ext/fiddle/lib/fiddle/pack.rb | 12 | ||||
-rw-r--r-- | test/fiddle/test_c_struct_entry.rb | 8 | ||||
-rw-r--r-- | test/fiddle/test_closure.rb | 12 | ||||
-rw-r--r-- | test/fiddle/test_func.rb | 17 |
10 files changed, 125 insertions, 23 deletions
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c index 3772dfda35..f39ff35f09 100644 --- a/ext/fiddle/closure.c +++ b/ext/fiddle/closure.c @@ -139,6 +139,20 @@ with_gvl_callback(void *ptr) rb_ary_push(params, rb_str_new_cstr(*((const char **)(x->args[i])))); break; + case TYPE_BOOL: + if (sizeof(bool) == sizeof(char)) { + rb_ary_push(params, CBOOL2RBBOOL(*(unsigned char *)x->args[i])); + } else if (sizeof(bool) == sizeof(short)) { + rb_ary_push(params, CBOOL2RBBOOL(*(unsigned short *)x->args[i])); + } else if (sizeof(bool) == sizeof(int)) { + rb_ary_push(params, CBOOL2RBBOOL(*(unsigned int *)x->args[i])); + } else if (sizeof(bool) == sizeof(long)) { + rb_ary_push(params, CBOOL2RBBOOL(*(unsigned long *)x->args[i])); + } else { + rb_raise(rb_eNotImpError, "bool isn't supported: %u", + (unsigned int)sizeof(bool)); + } + break; default: rb_raise(rb_eRuntimeError, "closure args: %d", type); } @@ -188,6 +202,13 @@ with_gvl_callback(void *ptr) /* Dangerous. Callback must keep reference of the String. */ *((const char **)(x->resp)) = StringValueCStr(ret); break; + case TYPE_BOOL: + if (sizeof(bool) == sizeof(long)) { + *(unsigned long *)x->resp = RB_TEST(ret); + } else { + *(ffi_arg *)x->resp = RB_TEST(ret); + } + break; default: rb_raise(rb_eRuntimeError, "closure retval: %d", type); } diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c index 66058d5d12..8c223ea959 100644 --- a/ext/fiddle/conversions.c +++ b/ext/fiddle/conversions.c @@ -3,25 +3,6 @@ #include <fiddle.h> VALUE -rb_fiddle_type_bool(void) -{ - if (sizeof(bool) == sizeof(char)) { - return INT2NUM(TYPE_UCHAR); - } else if (sizeof(bool) == sizeof(short)) { - return INT2NUM(TYPE_USHORT); - } else if (sizeof(bool) == sizeof(int)) { - return INT2NUM(TYPE_UINT); - } else if (sizeof(bool) == sizeof(long)) { - return INT2NUM(TYPE_ULONG); - } else { - rb_raise(rb_eNotImpError, - "bool isn't supported: %u", - (unsigned int)sizeof(bool)); - return RUBY_Qnil; - } -} - -VALUE rb_fiddle_type_ensure(VALUE type) { VALUE original_type = type; @@ -168,7 +149,7 @@ rb_fiddle_type_ensure(VALUE type) return INT2NUM(TYPE_UINTPTR_T); } else if (type_id == bool_id) { - return rb_fiddle_type_bool(); + return INT2NUM(TYPE_BOOL); } else { type = original_type; @@ -213,6 +194,21 @@ rb_fiddle_int_to_ffi_type(int type) return &ffi_type_double; case TYPE_CONST_STRING: return &ffi_type_pointer; + case TYPE_BOOL: + signed_p = 0; + if (sizeof(bool) == sizeof(char)) { + return rb_ffi_type_of(char); + } else if (sizeof(bool) == sizeof(short)) { + return rb_ffi_type_of(short); + return INT2NUM(TYPE_USHORT); + } 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); } @@ -284,8 +280,23 @@ rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst) dst->pointer = rb_string_value_cstr(src); } break; + case TYPE_BOOL: + if (sizeof(bool) == sizeof(char)) { + dst->uchar = RB_TEST(*src); + } else if (sizeof(bool) == sizeof(short)) { + dst->ushort = RB_TEST(*src); + } else if (sizeof(bool) == sizeof(int)) { + dst->uint = RB_TEST(*src); + } else if (sizeof(bool) == sizeof(long)) { + dst->ulong = RB_TEST(*src); + } else { + rb_raise(rb_eNotImpError, "bool isn't supported: %u", + (unsigned int)sizeof(bool)); + } + break; default: rb_raise(rb_eRuntimeError, "unknown type %d", type); + break; } } @@ -344,6 +355,19 @@ rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval) else { return Qnil; } + case TYPE_BOOL: + if (sizeof(bool) == sizeof(char)) { + return CBOOL2RBBOOL((unsigned char)retval.fffi_arg); + } else if (sizeof(bool) == sizeof(short)) { + return CBOOL2RBBOOL((unsigned short)retval.fffi_arg); + } else if (sizeof(bool) == sizeof(int)) { + return CBOOL2RBBOOL((unsigned int)retval.fffi_arg); + } else if (sizeof(bool) == sizeof(long)) { + return CBOOL2RBBOOL(retval.ulong); + } else { + rb_raise(rb_eNotImpError, "bool isn't supported: %u", + (unsigned int)sizeof(bool)); + } default: rb_raise(rb_eRuntimeError, "unknown type %d", type); } diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h index 5ea569e3ff..7a1e928d56 100644 --- a/ext/fiddle/conversions.h +++ b/ext/fiddle/conversions.h @@ -24,7 +24,6 @@ typedef union void * pointer; /* ffi_type_pointer */ } fiddle_generic; -VALUE rb_fiddle_type_bool(void); 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); @@ -51,4 +50,6 @@ VALUE generic_to_value(VALUE rettype, fiddle_generic retval); # define NUM2PTR(x) ((void*)(NUM2ULL(x))) #endif +#define CBOOL2RBBOOL(cbool) ((cbool) ? RUBY_Qtrue : RUBY_Qfalse) + #endif diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c index 49120704ab..f420d9fa3b 100644 --- a/ext/fiddle/fiddle.c +++ b/ext/fiddle/fiddle.c @@ -363,7 +363,7 @@ Init_fiddle(void) * * C type - bool */ - rb_define_const(mFiddleTypes, "BOOL" , rb_fiddle_type_bool()); + rb_define_const(mFiddleTypes, "BOOL" , INT2NUM(TYPE_BOOL)); /* Document-const: ALIGN_VOIDP * @@ -469,6 +469,12 @@ Init_fiddle(void) */ rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t))); + /* Document-const: ALIGN_BOOL + * + * The alignment size of a bool + */ + rb_define_const(mFiddle, "ALIGN_BOOL", INT2NUM(ALIGN_OF(bool))); + /* Document-const: WINDOWS * * Returns a boolean regarding whether the host is WIN32 diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h index 53db058807..348baa9ab9 100644 --- a/ext/fiddle/fiddle.h +++ b/ext/fiddle/fiddle.h @@ -126,6 +126,7 @@ #define TYPE_DOUBLE 8 #define TYPE_VARIADIC 9 #define TYPE_CONST_STRING 10 +#define TYPE_BOOL 11 #define TYPE_INT8_T TYPE_CHAR #define TYPE_UINT8_T -TYPE_INT8_T diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb index 09ffcef544..050708fb96 100644 --- a/ext/fiddle/lib/fiddle/import.rb +++ b/ext/fiddle/lib/fiddle/import.rb @@ -119,6 +119,8 @@ module Fiddle return SIZEOF_VOIDP when TYPE_CONST_STRING return SIZEOF_CONST_STRING + when TYPE_BOOL + return SIZEOF_BOOL else if defined?(TYPE_LONG_LONG) and ty == TYPE_LONG_LONG diff --git a/ext/fiddle/lib/fiddle/pack.rb b/ext/fiddle/lib/fiddle/pack.rb index 545b985d50..81088f402b 100644 --- a/ext/fiddle/lib/fiddle/pack.rb +++ b/ext/fiddle/lib/fiddle/pack.rb @@ -15,6 +15,7 @@ module Fiddle TYPE_USHORT => ALIGN_SHORT, TYPE_UINT => ALIGN_INT, TYPE_ULONG => ALIGN_LONG, + TYPE_BOOL => ALIGN_BOOL, } PACK_MAP = { @@ -30,6 +31,16 @@ module Fiddle TYPE_UINT => "I!", TYPE_ULONG => "L!", } + case SIZEOF_BOOL + when SIZEOF_CHAR + PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_UCHAR] + when SIZEOF_SHORT + PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_USHORT] + when SIZEOF_INT + PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_UINT] + when SIZEOF_LONG + PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_ULONG] + end SIZE_MAP = { TYPE_VOIDP => SIZEOF_VOIDP, @@ -43,6 +54,7 @@ module Fiddle TYPE_USHORT => SIZEOF_SHORT, TYPE_UINT => SIZEOF_INT, TYPE_ULONG => SIZEOF_LONG, + TYPE_BOOL => SIZEOF_BOOL, } if defined?(TYPE_LONG_LONG) ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[TYPE_ULONG_LONG] = ALIGN_LONG_LONG diff --git a/test/fiddle/test_c_struct_entry.rb b/test/fiddle/test_c_struct_entry.rb index 9fd16d7101..45de2efe21 100644 --- a/test/fiddle/test_c_struct_entry.rb +++ b/test/fiddle/test_c_struct_entry.rb @@ -8,7 +8,7 @@ end module Fiddle class TestCStructEntity < TestCase def test_class_size - types = [TYPE_DOUBLE, TYPE_CHAR] + types = [TYPE_DOUBLE, TYPE_CHAR, TYPE_DOUBLE, TYPE_BOOL] size = CStructEntity.size types @@ -20,6 +20,12 @@ module Fiddle 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 diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb index 825ea9651d..abb6bdbd32 100644 --- a/test/fiddle/test_closure.rb +++ b/test/fiddle/test_closure.rb @@ -81,6 +81,18 @@ module Fiddle 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.create(:int, [:void]) do |closure| assert(!closure.freed?) diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb index ff52f727d0..df79539e76 100644 --- a/test/fiddle/test_func.rb +++ b/test/fiddle/test_func.rb @@ -145,5 +145,22 @@ module Fiddle assert_equal("string: He, const string: World, uint: 29\n", output_buffer[0, written]) 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) |