Spec-Zone.ru › Ruby 3.2

class Fiddle::Handle

Parent:
Объект

Способ доступа к динамической библиотеке

Пример

Настройка

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 задан, используется DEFAULT, что эквивалентно RTLD_DEFAULT. Смотрите man 3 dlopen для получения дополнительной информации.

lib = Fiddle::Handle.new

Значение по умолчанию зависит от ОС и предоставляет дескриптор для всех уже загруженных библиотек. Например, в большинстве случаев вы можете использовать это для доступа к функциям libc или функциям Ruby, таким как rb_str_new.

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;
    }
}

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

[](p1)

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

Псевдоним для: 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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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