summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2021-11-11 18:06:33 +0900
committernagachika <nagachika@ruby-lang.org>2021-11-22 10:51:35 +0900
commit4716a8e157044b3a3a490c96957eb6c9204d70f1 (patch)
treea3c29a11af91d07f9f98102e4591e450051395bc
parentb789399c099b51cd60a07fe686145c451d0a5d4e (diff)
Bump fiddle version to 1.0.8
-rw-r--r--ext/fiddle/closure.c26
-rw-r--r--ext/fiddle/conversions.h1
-rw-r--r--ext/fiddle/extconf.rb43
-rw-r--r--ext/fiddle/function.c11
-rw-r--r--ext/fiddle/lib/fiddle.rb12
-rw-r--r--ext/fiddle/lib/fiddle/cparser.rb6
-rw-r--r--ext/fiddle/lib/fiddle/version.rb2
-rw-r--r--test/fiddle/helper.rb4
-rw-r--r--test/fiddle/test_closure.rb25
-rw-r--r--test/fiddle/test_cparser.rb56
10 files changed, 166 insertions, 20 deletions
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c
index 40cee55e9a..3679e5c9ad 100644
--- a/ext/fiddle/closure.c
+++ b/ext/fiddle/closure.c
@@ -130,6 +130,10 @@ with_gvl_callback(void *ptr)
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;
default:
rb_raise(rb_eRuntimeError, "closure args: %d", type);
}
@@ -175,6 +179,10 @@ with_gvl_callback(void *ptr)
*(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;
default:
rb_raise(rb_eRuntimeError, "closure retval: %d", type);
}
@@ -221,6 +229,7 @@ initialize(int rbargc, VALUE argv[], VALUE self)
{
VALUE ret;
VALUE args;
+ VALUE normalized_args;
VALUE abi;
fiddle_closure * cl;
ffi_cif * cif;
@@ -239,21 +248,26 @@ initialize(int rbargc, VALUE argv[], VALUE self)
cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
+ normalized_args = rb_ary_new_capa(argc);
for (i = 0; i < argc; i++) {
- int type = NUM2INT(RARRAY_AREF(args, i));
- cl->argv[i] = INT2FFI_TYPE(type);
+ 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;
+ ret = rb_fiddle_type_ensure(ret);
rb_iv_set(self, "@ctype", ret);
- rb_iv_set(self, "@args", args);
+ rb_iv_set(self, "@args", normalized_args);
cif = &cl->cif;
pcl = cl->pcl;
- result = ffi_prep_cif(cif, NUM2INT(abi), argc,
- INT2FFI_TYPE(NUM2INT(ret)),
- cl->argv);
+ 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);
diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h
index 1de956e90c..c7c12a9234 100644
--- a/ext/fiddle/conversions.h
+++ b/ext/fiddle/conversions.h
@@ -24,7 +24,6 @@ typedef union
void * pointer; /* ffi_type_pointer */
} 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);
diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb
index 6d1d5104a1..6ca685317e 100644
--- a/ext/fiddle/extconf.rb
+++ b/ext/fiddle/extconf.rb
@@ -3,6 +3,47 @@ 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 = enable_config('bundled-libffi')
@@ -159,6 +200,8 @@ elsif have_header "windows.h"
%w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
abort "missing function #{func}" unless have_func(func)
end
+
+ have_library "ws2_32"
end
have_const('FFI_STDCALL', ffi_header)
diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c
index 1d82bc8a3e..d15a54bfa6 100644
--- a/ext/fiddle/function.c
+++ b/ext/fiddle/function.c
@@ -375,10 +375,17 @@ function_call(int argc, VALUE argv[], VALUE self)
(void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);
}
- rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
+ {
+ int errno_keep = errno;
#if defined(_WIN32)
- rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
+ int socket_error = WSAGetLastError();
+ rb_funcall(mFiddle, rb_intern("win32_last_error="), 1,
+ INT2NUM(errno_keep));
+ 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);
diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb
index 3fdf525b4c..4512989310 100644
--- a/ext/fiddle/lib/fiddle.rb
+++ b/ext/fiddle/lib/fiddle.rb
@@ -17,6 +17,18 @@ module Fiddle
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
# Returns the last +Error+ of the current executing +Thread+ or nil if none
diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb
index 8a269393c6..93a05513c9 100644
--- a/ext/fiddle/lib/fiddle/cparser.rb
+++ b/ext/fiddle/lib/fiddle/cparser.rb
@@ -148,9 +148,11 @@ module Fiddle
#
def parse_ctype(ty, tymap=nil)
tymap ||= {}
- case ty
- when Array
+ 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/
diff --git a/ext/fiddle/lib/fiddle/version.rb b/ext/fiddle/lib/fiddle/version.rb
index d80cb7078f..a699371ee4 100644
--- a/ext/fiddle/lib/fiddle/version.rb
+++ b/ext/fiddle/lib/fiddle/version.rb
@@ -1,3 +1,3 @@
module Fiddle
- VERSION = "1.0.6"
+ VERSION = "1.0.8"
end
diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb
index f38f9036a3..a6e2019924 100644
--- a/test/fiddle/helper.rb
+++ b/test/fiddle/helper.rb
@@ -47,8 +47,8 @@ when /linux/
libm_so = libc_so
else
# glibc
- libc_so = File.join(libdir, "libc.so.6")
- libm_so = File.join(libdir, "libm.so.6")
+ libc_so = "libc.so.6"
+ libm_so = "libm.so.6"
end
when /mingw/, /mswin/
require "rbconfig"
diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb
index 2de0660725..9e748bf5ee 100644
--- a/test/fiddle/test_closure.rb
+++ b/test/fiddle/test_closure.rb
@@ -20,6 +20,18 @@ module Fiddle
end
end
+ def test_type_symbol
+ closure = Closure.new(:int, [:void])
+ assert_equal([
+ TYPE_INT,
+ [TYPE_VOID],
+ ],
+ [
+ closure.instance_variable_get(:@ctype),
+ closure.instance_variable_get(:@args),
+ ])
+ end
+
def test_call
closure = Class.new(Closure) {
def call
@@ -42,6 +54,19 @@ module Fiddle
assert_equal 10, func.call(10)
end
+ def test_const_string
+ closure_class = Class.new(Closure) do
+ def call(string)
+ @return_string = "Hello! #{string}"
+ @return_string
+ end
+ end
+ closure = closure_class.new(:const_string, [:const_string])
+
+ func = Function.new(closure, [:const_string], :const_string)
+ assert_equal("Hello! World!", func.call("World!"))
+ end
+
def test_block_caller
cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one|
one
diff --git a/test/fiddle/test_cparser.rb b/test/fiddle/test_cparser.rb
index ef8cec5daa..24e1800e59 100644
--- a/test/fiddle/test_cparser.rb
+++ b/test/fiddle/test_cparser.rb
@@ -12,53 +12,77 @@ module Fiddle
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('signed short'))
+ assert_equal(TYPE_SHORT, parse_ctype('const signed short'))
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('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'))
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('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('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'))
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_undefined_ctype
@@ -66,7 +90,10 @@ module Fiddle
end
def test_undefined_ctype_with_type_alias
- assert_equal(-TYPE_LONG, parse_ctype('DWORD', {"DWORD" => "unsigned long"}))
+ 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)
@@ -83,11 +110,21 @@ module Fiddle
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(['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(['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
@@ -178,15 +215,22 @@ module Fiddle
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('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*)'])
+ 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')
+ assert_equal([[TYPE_VOIDP, TYPE_VOIDP], ['cb', 'data']],
+ parse_struct_signature('void (*cb)(const char*), const char* data'))
end
def test_struct_string