класс Fiddle::Handle
Способ доступа к динамической библиотеке
Пример
Настройка
libc_so = "/lib64/libc.so.6" => "/lib64/libc.so.6" @handle = Fiddle::Handle.new(libc_so) => #<Fiddle::Handle:0x00000000d69ef8>
Настройка с флагами
libc_so = "/lib64/libc.so.6" => "/lib64/libc.so.6" @handle = Fiddle::Handle.new(libc_so, Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL) => #<Fiddle::Handle:0x00000000d69ef8>
См. RTLD_LAZY и RTLD_GLOBAL
Адреса символов
strcpy_addr = @handle['strcpy'] => 140062278451968
или
strcpy_addr = @handle.sym('strcpy')
=> 140062278451968 Константы
- DEFAULT
-
Предопределённый псевдо-дескриптор RTLD_DEFAULT
Найдёт первое вхождение нужного символа, используя стандартный порядок поиска библиотек
- NEXT
-
Предопределённый псевдо-дескриптор RTLD_NEXT
Найдёт следующее вхождение функции в порядке поиска после текущей библиотеки.
- RTLD_GLOBAL
-
Флаг rtld
Fiddle::Handle.Символы, определённые этой библиотекой, станут доступными для разрешения символов в последующих загруженных библиотеках.
- RTLD_LAZY
-
Флаг rtld
Fiddle::Handle.Выполнить отложенную привязку. Разрешить символы только когда выполняется код, который на них ссылается. Если на символ никогда не ссылаются, то он никогда не разрешается. (Отложенная привязка выполняется только для ссылок на функции; ссылки на переменные всегда связываются немедленно при загрузке библиотеки.)
- RTLD_NOW
-
Флаг rtld
Fiddle::Handle.Если это значение указано или переменная окружения LD_BIND_NOW установлена в непустую строку, все неопределённые символы в библиотеке разрешаются до того, как
Fiddle.dlopenвернёт результат. Если это невозможно, возвращается ошибка.
Методы публичного класса
Исходный код
static VALUE
rb_fiddle_handle_s_sym(VALUE self, VALUE sym)
{
return fiddle_handle_sym(RTLD_NEXT, sym);
} Получить адрес как Integer для функции с именем name. Функция ищется через dlsym с RTLD_NEXT.
См. man(3) dlsym() для получения дополнительной информации.
Исходный код
static VALUE
rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self)
{
void *ptr;
struct dl_handle *fiddle_handle;
VALUE lib, flag;
char *clib;
int cflag;
const char *err;
switch( rb_scan_args(argc, argv, "02", &lib, &flag) ){
case 0:
clib = NULL;
cflag = RTLD_LAZY | RTLD_GLOBAL;
break;
case 1:
clib = NIL_P(lib) ? NULL : StringValueCStr(lib);
cflag = RTLD_LAZY | RTLD_GLOBAL;
break;
case 2:
clib = NIL_P(lib) ? NULL : StringValueCStr(lib);
cflag = NUM2INT(flag);
break;
default:
rb_bug("rb_fiddle_handle_new");
}
#if defined(_WIN32)
if( !clib ){
HANDLE rb_libruby_handle(void);
ptr = rb_libruby_handle();
}
else if( STRCASECMP(clib, "libc") == 0
# ifdef RUBY_COREDLL
|| STRCASECMP(clib, RUBY_COREDLL) == 0
|| STRCASECMP(clib, RUBY_COREDLL".dll") == 0
# endif
){
# ifdef _WIN32_WCE
ptr = dlopen("coredll.dll", cflag);
# else
(void)cflag;
ptr = w32_coredll();
# endif
}
else
#endif
ptr = dlopen(clib, cflag);
#if defined(HAVE_DLERROR)
if( !ptr && (err = dlerror()) ){
rb_raise(rb_eFiddleDLError, "%s", err);
}
#else
if( !ptr ){
err = dlerror();
rb_raise(rb_eFiddleDLError, "%s", err);
}
#endif
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){
dlclose(fiddle_handle->ptr);
}
fiddle_handle->ptr = ptr;
fiddle_handle->open = 1;
fiddle_handle->enable_close = 0;
if( rb_block_given_p() ){
rb_ensure(rb_yield, self, rb_fiddle_handle_close, self);
}
return Qnil;
} Создать новый обработчик, который открывает library с flags.
Если library не указан или nil задан, используется DEFAULT, что эквивалентно RTLD_DEFAULT. Подробнее см. man 3 dlopen.
lib = Fiddle::Handle.new
Значение по умолчанию зависит от ОС и предоставляет обработчик для всех уже загруженных библиотек. Например, в большинстве случаев вы можете использовать это для доступа к функциям libc или функциям Ruby, таким как rb_str_new.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 488
def initialize(libname = nil, flags = RTLD_LAZY | RTLD_GLOBAL)
begin
@lib = FFI::DynamicLibrary.open(libname, flags)
rescue LoadError, RuntimeError # LoadError for JRuby, RuntimeError for TruffleRuby
raise DLError, "Could not open #{libname}"
end
@open = true
begin
yield(self)
ensure
self.close
end if block_given?
end Исходный код
static VALUE
rb_fiddle_handle_s_sym(VALUE self, VALUE sym)
{
return fiddle_handle_sym(RTLD_NEXT, sym);
} Получить адрес как Integer для функции с именем name.
Исходный код
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_close(VALUE self)
{
struct dl_handle *fiddle_handle;
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
if(fiddle_handle->open) {
int ret = dlclose(fiddle_handle->ptr);
fiddle_handle->open = 0;
/* Check dlclose for successful return value */
if(ret) {
#if defined(HAVE_DLERROR)
rb_raise(rb_eFiddleDLError, "%s", dlerror());
#else
rb_raise(rb_eFiddleDLError, "could not close handle");
#endif
}
return INT2NUM(ret);
}
rb_raise(rb_eFiddleDLError, "dlclose() called too many times");
UNREACHABLE;
} Закрыть этот обработчик.
Вызов close более одного раза вызовет исключение Fiddle::DLError.
Исходный код
static VALUE
rb_fiddle_handle_close_enabled_p(VALUE self)
{
struct dl_handle *fiddle_handle;
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
if(fiddle_handle->enable_close) return Qtrue;
return Qfalse;
} Возвращает true, если dlclose() будет вызван при сборе мусора этого обработчика.
См. man(3) dlclose() для получения дополнительной информации.
Исходный код
static VALUE
rb_fiddle_handle_disable_close(VALUE self)
{
struct dl_handle *fiddle_handle;
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
fiddle_handle->enable_close = 0;
return Qnil;
} Отключить вызов dlclose() при сборе мусора этого обработчика.
Исходный код
static VALUE
rb_fiddle_handle_enable_close(VALUE self)
{
struct dl_handle *fiddle_handle;
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
fiddle_handle->enable_close = 1;
return Qnil;
} Включить вызов dlclose() при сборе мусора этого обработчика.
Исходный код
static VALUE
rb_fiddle_handle_file_name(VALUE self)
{
struct dl_handle *fiddle_handle;
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
#if defined(HAVE_DLINFO) && defined(HAVE_CONST_RTLD_DI_LINKMAP)
{
struct link_map *lm = NULL;
int res = dlinfo(fiddle_handle->ptr, RTLD_DI_LINKMAP, &lm);
if (res == 0 && lm != NULL) {
return rb_str_new_cstr(lm->l_name);
}
else {
#if defined(HAVE_DLERROR)
rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
#else
rb_raise(rb_eFiddleDLError, "could not get handle file name");
#endif
}
}
#elif defined(HAVE_GETMODULEFILENAME)
{
char filename[MAX_PATH];
DWORD res = GetModuleFileName(fiddle_handle->ptr, filename, MAX_PATH);
if (res == 0) {
rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
}
return rb_str_new_cstr(filename);
}
#else
(void)fiddle_handle;
return Qnil;
#endif
} Возвращает имя файла этого обработчика.
Исходный код
static VALUE
rb_fiddle_handle_sym(VALUE self, VALUE sym)
{
struct dl_handle *fiddle_handle;
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
if( ! fiddle_handle->open ){
rb_raise(rb_eFiddleDLError, "closed handle");
}
return fiddle_handle_sym(fiddle_handle->ptr, sym);
} Получить адрес как Integer для функции с именем name.
Исходный код
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
rb_fiddle_handle_to_i(VALUE self)
{
struct dl_handle *fiddle_handle;
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
return PTR2NUM(fiddle_handle->ptr);
} Возвращает адрес памяти для этого обработчика.
Исходный код
static VALUE
rb_fiddle_handle_to_ptr(VALUE self)
{
struct dl_handle *fiddle_handle;
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
return rb_fiddle_ptr_new_wrap(fiddle_handle->ptr, 0, 0, self, 0);
} Возвращает Fiddle::Pointer этого обработчика.
Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.