[ruby/fiddle] Add sym_defined?
methods to test if a symbol is defined (https://github.com/ruby/fiddle/pull/108)
I would like to check if a symbol is defined before trying to access it. Some symbols aren't available on all platforms, so instead of raising an exception, I want to check if it's defined first. Today we have to do: ```ruby begin addr = Fiddle::Handle.sym("something") # do something rescue Fiddle::DLError end ``` I want to write this: ```ruby if Fiddle::Handle.sym_defined?("something") addr = Fiddle::Handle.sym("something") # do something end ``` https://github.com/ruby/fiddle/commit/9d3371de13 Co-authored-by: Sutou Kouhei <kou@clear-code.com>
This commit is contained in:
parent
755d99e878
commit
0097c7f388
@ -321,8 +321,10 @@ rb_fiddle_handle_s_sym(VALUE self, VALUE sym)
|
|||||||
return fiddle_handle_sym(RTLD_NEXT, sym);
|
return fiddle_handle_sym(RTLD_NEXT, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
typedef void (*fiddle_void_func)(void);
|
||||||
fiddle_handle_sym(void *handle, VALUE symbol)
|
|
||||||
|
static fiddle_void_func
|
||||||
|
fiddle_handle_find_func(void *handle, VALUE symbol)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_DLERROR)
|
#if defined(HAVE_DLERROR)
|
||||||
const char *err;
|
const char *err;
|
||||||
@ -330,13 +332,13 @@ fiddle_handle_sym(void *handle, VALUE symbol)
|
|||||||
#else
|
#else
|
||||||
# define CHECK_DLERROR
|
# define CHECK_DLERROR
|
||||||
#endif
|
#endif
|
||||||
void (*func)();
|
fiddle_void_func func;
|
||||||
const char *name = StringValueCStr(symbol);
|
const char *name = StringValueCStr(symbol);
|
||||||
|
|
||||||
#ifdef HAVE_DLERROR
|
#ifdef HAVE_DLERROR
|
||||||
dlerror();
|
dlerror();
|
||||||
#endif
|
#endif
|
||||||
func = (void (*)())(VALUE)dlsym(handle, name);
|
func = (fiddle_void_func)(VALUE)dlsym(handle, name);
|
||||||
CHECK_DLERROR;
|
CHECK_DLERROR;
|
||||||
#if defined(FUNC_STDCALL)
|
#if defined(FUNC_STDCALL)
|
||||||
if( !func ){
|
if( !func ){
|
||||||
@ -379,6 +381,53 @@ fiddle_handle_sym(void *handle, VALUE symbol)
|
|||||||
xfree(name_n);
|
xfree(name_n);
|
||||||
}
|
}
|
||||||
#endif
|
#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 ){
|
if( !func ){
|
||||||
rb_raise(rb_eFiddleDLError, "unknown symbol \"%"PRIsVALUE"\"", symbol);
|
rb_raise(rb_eFiddleDLError, "unknown symbol \"%"PRIsVALUE"\"", symbol);
|
||||||
}
|
}
|
||||||
@ -468,6 +517,7 @@ Init_fiddle_handle(void)
|
|||||||
rb_cHandle = rb_define_class_under(mFiddle, "Handle", rb_cObject);
|
rb_cHandle = rb_define_class_under(mFiddle, "Handle", rb_cObject);
|
||||||
rb_define_alloc_func(rb_cHandle, rb_fiddle_handle_s_allocate);
|
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", 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);
|
rb_define_singleton_method(rb_cHandle, "[]", rb_fiddle_handle_s_sym, 1);
|
||||||
|
|
||||||
/* Document-const: NEXT
|
/* Document-const: NEXT
|
||||||
@ -526,6 +576,7 @@ Init_fiddle_handle(void)
|
|||||||
rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 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, "sym", rb_fiddle_handle_sym, 1);
|
||||||
rb_define_method(rb_cHandle, "[]", 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, "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, "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, "enable_close", rb_fiddle_handle_enable_close, 0);
|
||||||
|
@ -22,12 +22,14 @@ module Fiddle
|
|||||||
def test_static_sym_unknown
|
def test_static_sym_unknown
|
||||||
assert_raise(DLError) { Fiddle::Handle.sym('fooo') }
|
assert_raise(DLError) { Fiddle::Handle.sym('fooo') }
|
||||||
assert_raise(DLError) { Fiddle::Handle['fooo'] }
|
assert_raise(DLError) { Fiddle::Handle['fooo'] }
|
||||||
|
refute Fiddle::Handle.sym_defined?('fooo')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_static_sym
|
def test_static_sym
|
||||||
begin
|
begin
|
||||||
# Linux / Darwin / FreeBSD
|
# Linux / Darwin / FreeBSD
|
||||||
refute_nil Fiddle::Handle.sym('dlopen')
|
refute_nil Fiddle::Handle.sym('dlopen')
|
||||||
|
assert Fiddle::Handle.sym_defined?('dlopen')
|
||||||
assert_equal Fiddle::Handle.sym('dlopen'), Fiddle::Handle['dlopen']
|
assert_equal Fiddle::Handle.sym('dlopen'), Fiddle::Handle['dlopen']
|
||||||
return
|
return
|
||||||
rescue
|
rescue
|
||||||
@ -54,6 +56,7 @@ module Fiddle
|
|||||||
handle = Fiddle::Handle.new(LIBC_SO)
|
handle = Fiddle::Handle.new(LIBC_SO)
|
||||||
assert_raise(DLError) { handle.sym('fooo') }
|
assert_raise(DLError) { handle.sym('fooo') }
|
||||||
assert_raise(DLError) { handle['fooo'] }
|
assert_raise(DLError) { handle['fooo'] }
|
||||||
|
refute handle.sym_defined?('fooo')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_sym_with_bad_args
|
def test_sym_with_bad_args
|
||||||
@ -66,6 +69,7 @@ module Fiddle
|
|||||||
handle = Handle.new(LIBC_SO)
|
handle = Handle.new(LIBC_SO)
|
||||||
refute_nil handle.sym('calloc')
|
refute_nil handle.sym('calloc')
|
||||||
refute_nil handle['calloc']
|
refute_nil handle['calloc']
|
||||||
|
assert handle.sym_defined?('calloc')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_handle_close
|
def test_handle_close
|
||||||
|
Loading…
x
Reference in New Issue
Block a user