Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rb_ext_resolve_symbol: C API to resolve and return externed symbols […
…Feature #20005] This is a C API for extensions to resolve and get function symbols of other extensions. Extensions can check the expected symbol is correctly loaded and accessible, and use it if it is available. Otherwise, extensions can raise their own error to guide users to setup their environments correctly and what's missing.
- Loading branch information
Showing
18 changed files
with
277 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
create_makefile('-test-/load/resolve_symbol_resolver') |
50 changes: 50 additions & 0 deletions
50
ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#include <ruby.h> | ||
#include "ruby/internal/intern/load.h" | ||
|
||
typedef VALUE(*target_func)(VALUE); | ||
|
||
static target_func rst_any_method; | ||
|
||
VALUE | ||
rsr_any_method(VALUE klass) | ||
{ | ||
return rst_any_method((VALUE)NULL); | ||
} | ||
|
||
VALUE | ||
rsr_try_resolve_fname(VALUE klass) | ||
{ | ||
target_func rst_something_missing = | ||
(target_func) rb_ext_resolve_symbol("-test-/load/resolve_symbol_missing", "rst_any_method"); | ||
if (rst_something_missing == NULL) { | ||
// This should be done in Init_*, so the error is LoadError | ||
rb_raise(rb_eLoadError, "symbol not found: missing fname"); | ||
} | ||
return Qtrue; | ||
} | ||
|
||
VALUE | ||
rsr_try_resolve_sname(VALUE klass) | ||
{ | ||
target_func rst_something_missing = | ||
(target_func)rb_ext_resolve_symbol("-test-/load/resolve_symbol_target", "rst_something_missing"); | ||
if (rst_something_missing == NULL) { | ||
// This should be done in Init_*, so the error is LoadError | ||
rb_raise(rb_eLoadError, "symbol not found: missing sname"); | ||
} | ||
return Qtrue; | ||
} | ||
|
||
void | ||
Init_resolve_symbol_resolver(void) | ||
{ | ||
VALUE mod = rb_define_module("ResolveSymbolResolver"); | ||
rb_define_singleton_method(mod, "any_method", rsr_any_method, 0); | ||
rb_define_singleton_method(mod, "try_resolve_fname", rsr_try_resolve_fname, 0); | ||
rb_define_singleton_method(mod, "try_resolve_sname", rsr_try_resolve_sname, 0); | ||
|
||
rst_any_method = (target_func)rb_ext_resolve_symbol("-test-/load/resolve_symbol_target", "rst_any_method"); | ||
if (rst_any_method == NULL) { | ||
rb_raise(rb_eLoadError, "resolve_symbol_target is not loaded"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
create_makefile('-test-/load/resolve_symbol_target') |
15 changes: 15 additions & 0 deletions
15
ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include <ruby.h> | ||
#include "resolve_symbol_target.h" | ||
|
||
VALUE | ||
rst_any_method(VALUE klass) | ||
{ | ||
return rb_str_new_cstr("from target"); | ||
} | ||
|
||
void | ||
Init_resolve_symbol_target(void) | ||
{ | ||
VALUE mod = rb_define_module("ResolveSymbolTarget"); | ||
rb_define_singleton_method(mod, "any_method", rst_any_method, 0); | ||
} |
4 changes: 4 additions & 0 deletions
4
ext/-test-/load/resolve_symbol_target/resolve_symbol_target.def
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
LIBRARY resolve_symbol_target | ||
EXPORTS | ||
Init_resolve_symbol_target | ||
rst_any_method |
4 changes: 4 additions & 0 deletions
4
ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#include <ruby.h> | ||
#include "ruby/internal/dllexport.h" | ||
|
||
RUBY_EXTERN VALUE rst_any_method(VALUE); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
create_makefile('-test-/load/stringify_symbols') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#include <ruby.h> | ||
#include "ruby/internal/intern/load.h" | ||
#include "ruby/util.h" | ||
|
||
#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG | ||
# define UINTPTR2NUM ULL2NUM | ||
#elif SIZEOF_INTPTR_T == SIZEOF_LONG | ||
# define UINTPTR2NUM ULONG2NUM | ||
#else | ||
# define UINTPTR2NUM UINT2NUM | ||
#endif | ||
|
||
static VALUE | ||
stringify_symbol(VALUE klass, VALUE fname, VALUE sname) | ||
{ | ||
void *ptr = rb_ext_resolve_symbol(StringValueCStr(fname), StringValueCStr(sname)); | ||
if (ptr == NULL) { | ||
return Qnil; | ||
} | ||
uintptr_t uintptr = (uintptr_t)ptr; | ||
return UINTPTR2NUM(uintptr); | ||
} | ||
|
||
void | ||
Init_stringify_symbols(void) | ||
{ | ||
VALUE mod = rb_define_module("StringifySymbols"); | ||
rb_define_singleton_method(mod, "stringify_symbol", stringify_symbol, 2); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
create_makefile('-test-/load/stringify_target') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include <ruby.h> | ||
#include "stringify_target.h" | ||
|
||
VALUE | ||
stt_any_method(VALUE klass) | ||
{ | ||
return rb_str_new_cstr("from target"); | ||
} | ||
|
||
void | ||
Init_stringify_target(void) | ||
{ | ||
VALUE mod = rb_define_module("StringifyTarget"); | ||
rb_define_singleton_method(mod, "any_method", stt_any_method, 0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
LIBRARY stringify_target | ||
EXPORTS | ||
Init_stringify_target | ||
stt_any_method |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#include <ruby.h> | ||
#include "ruby/internal/dllexport.h" | ||
|
||
RUBY_EXTERN VALUE stt_any_method(VALUE); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# frozen_string_literal: true | ||
require 'test/unit' | ||
|
||
class Test_Load_ResolveSymbol < Test::Unit::TestCase | ||
def test_load_resolve_symbol_resolver | ||
feature = "Feature #20005" | ||
assert_raise(LoadError, "resolve_symbol_target is not loaded") { | ||
require '-test-/load/resolve_symbol_resolver' | ||
} | ||
require '-test-/load/resolve_symbol_target' | ||
assert_nothing_raised(LoadError, "#{feature} resolver can be loaded") { | ||
require '-test-/load/resolve_symbol_resolver' | ||
} | ||
assert_not_nil ResolveSymbolResolver | ||
assert_equal "from target", ResolveSymbolResolver.any_method | ||
|
||
assert_raise(LoadError, "tries to resolve missing feature name, and it should raise LoadError") { | ||
ResolveSymbolResolver.try_resolve_fname | ||
} | ||
assert_raise(LoadError, "tries to resolve missing symbol name, and it should raise LoadError") { | ||
ResolveSymbolResolver.try_resolve_sname | ||
} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# frozen_string_literal: true | ||
require 'test/unit' | ||
|
||
class Test_Load_stringify_symbols < Test::Unit::TestCase | ||
def test_load_stringify_symbol_required_extensions | ||
require '-test-/load/stringify_symbols' | ||
require '-test-/load/stringify_target' | ||
r1 = StringifySymbols.stringify_symbol("-test-/load/stringify_target", "stt_any_method") | ||
assert_not_nil r1 | ||
r2 = StringifySymbols.stringify_symbol("-test-/load/stringify_target.so", "stt_any_method") | ||
assert_equal r1, r2, "resolved symbols should be equal even with or without .so suffix" | ||
end | ||
|
||
def test_load_stringify_symbol_statically_linked | ||
require '-test-/load/stringify_symbols' | ||
# "complex.so" is actually not a statically linked extension. | ||
# But it is registered in $LOADED_FEATURES, so it can be a target of this test. | ||
r1 = StringifySymbols.stringify_symbol("complex", "rb_complex_minus") | ||
assert_not_nil r1 | ||
r2 = StringifySymbols.stringify_symbol("complex.so", "rb_complex_minus") | ||
assert_equal r1, r2 | ||
end | ||
|
||
def test_load_stringify_symbol_missing_target | ||
require '-test-/load/stringify_symbols' | ||
r1 = assert_nothing_raised { | ||
StringifySymbols.stringify_symbol("something_missing", "unknown_method") | ||
} | ||
assert_nil r1 | ||
r2 = assert_nothing_raised { | ||
StringifySymbols.stringify_symbol("complex.so", "unknown_method") | ||
} | ||
assert_nil r2 | ||
end | ||
end |