[前][次][番号順一覧][スレッド一覧]

ruby-changes:73898

From: Aaron <ko1@a...>
Date: Fri, 7 Oct 2022 15:20:59 +0900 (JST)
Subject: [ruby-changes:73898] 0097c7f388 (master): [ruby/fiddle] Add `sym_defined?` methods to test if a symbol is defined (https://github.com/ruby/fiddle/pull/108)

https://git.ruby-lang.org/ruby.git/commit/?id=0097c7f388

From 0097c7f3887ad8dd5493cb3696ac6368dc4a1014 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <tenderlove@r...>
Date: Tue, 13 Sep 2022 08:27:59 -0700
Subject: [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@c...>
---
 ext/fiddle/handle.c        | 59 ++++++++++++++++++++++++++++++++++++++++++----
 test/fiddle/test_handle.rb |  4 ++++
 2 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c
index 76b90909d3..ae8cc3a581 100644
--- a/ext/fiddle/handle.c
+++ b/ext/fiddle/handle.c
@@ -321,8 +321,10 @@ rb_fiddle_handle_s_sym(VALUE self, VALUE sym) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/handle.c#L321
     return fiddle_handle_sym(RTLD_NEXT, sym);
 }
 
-static VALUE
-fiddle_handle_sym(void *handle, VALUE symbol)
+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;
@@ -330,13 +332,13 @@ fiddle_handle_sym(void *handle, VALUE symbol) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/handle.c#L332
 #else
 # define CHECK_DLERROR
 #endif
-    void (*func)();
+    fiddle_void_func func;
     const char *name = StringValueCStr(symbol);
 
 #ifdef HAVE_DLERROR
     dlerror();
 #endif
-    func = (void (*)())(VALUE)dlsym(handle, name);
+    func = (fiddle_void_func)(VALUE)dlsym(handle, name);
     CHECK_DLERROR;
 #if defined(FUNC_STDCALL)
     if( !func ){
@@ -379,6 +381,53 @@ fiddle_handle_sym(void *handle, VALUE symbol) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/handle.c#L381
 	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);
     }
@@ -468,6 +517,7 @@ Init_fiddle_handle(void) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/handle.c#L517
     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
@@ -526,6 +576,7 @@ Init_fiddle_handle(void) https://github.com/ruby/ruby/blob/trunk/ext/fiddle/handle.c#L576
     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);
diff --git a/test/fiddle/test_handle.rb b/test/fiddle/test_handle.rb
index 7e3ff9d844..3bb80b75e2 100644
--- a/test/fiddle/test_handle.rb
+++ b/test/fiddle/test_handle.rb
@@ -22,12 +22,14 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/test/fiddle/test_handle.rb#L22
     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
       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
@@ -54,6 +56,7 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/test/fiddle/test_handle.rb#L56
       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
@@ -66,6 +69,7 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/test/fiddle/test_handle.rb#L69
       handle = Handle.new(LIBC_SO)
       refute_nil handle.sym('calloc')
       refute_nil handle['calloc']
+      assert handle.sym_defined?('calloc')
     end
 
     def test_handle_close
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]