Spec-Zone.ru › Ruby 3.4
  1. Fiddle::
  2. Handle

class Fiddle::Handle

Родитель:
Object

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

DEFAULT

Предопределённый псевдодескриптор RTLD_DEFAULT

Находит первое вхождение нужного символа, используя порядок поиска библиотек по умолчанию

NEXT

NEXT

Предопределённый псевдодескриптор RTLD_NEXT

Находит следующее вхождение функции в порядке поиска после текущей библиотеки.

RTLD_GLOBAL

RTLD_GLOBAL

Флаг rtld Fiddle::Handle.

Символы, определённые этой библиотекой, становятся доступными для разрешения символов в библиотеках, загруженных впоследствии.

RTLD_LAZY

RTLD_LAZY

Флаг rtld Fiddle::Handle.

Выполняет ленивую привязку. Символы разрешаются только при выполнении кода, который на них ссылается. Если на символ никогда не ссылаются, он не разрешается. (Ленивая привязка выполняется только для ссылок на функции; ссылки на переменные всегда привязываются немедленно при загрузке библиотеки.)

RTLD_NOW

RTLD_NOW

Флаг rtld Fiddle::Handle.

Если указано это значение или переменная среды LD_BIND_NOW установлена в непустую строку, все неопределённые символы в библиотеке разрешаются до возврата Fiddle.dlopen. Если это невозможно, возвращается ошибка.

Открытые методы класса

sym(name) Показать исходный код
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().

new(library = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL) Показать исходный код
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.

new (libname = nil, flags = RTLD_LAZY | RTLD_GLOBAL) { |self| ... } Показать исходный код
# 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
sym(name) Показать исходный код
static VALUE
rb_fiddle_handle_s_sym(VALUE self, VALUE sym)
{
    return fiddle_handle_sym(RTLD_NEXT, sym);
}

Получает адрес в виде Integer функции с именем name.

sym_defined? (p1) Показать исходный код
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;
    }
}

Открытые методы экземпляра

[]
Псевдоним для: sym
close Показать исходный код
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.

close_enabled? Показать исходный код
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().

disable_close Показать исходный код
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() при сборке мусора для этого дескриптора.

enable_close Показать исходный код
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() при сборке мусора для этого дескриптора.

file_name Показать исходный код
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
}

Возвращает имя файла этого дескриптора.

sym(name) Показать исходный код
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.

Также имеет псевдонимы: [], []
sym_defined? (p1) Показать исходный код
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;
    }
}
to_i Показать исходный код
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);
}

Возвращает адрес памяти этого дескриптора.

to_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–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API