class Fiddle::Handle
The Fiddle::Handle is the way to access the dynamic library
Пример
Настройка
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);
} Получить адрес как Целое число для функции с именем 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 : SafeStringValueCStr(lib);
cflag = RTLD_LAZY | RTLD_GLOBAL;
break;
case 2:
clib = NIL_P(lib) ? NULL : SafeStringValueCStr(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_eFiddleError, "%s", err);
}
#else
if( !ptr ){
err = dlerror();
rb_raise(rb_eFiddleError, "%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.
Если библиотека не указана или используется nil, используется DEFAULT, что эквивалентно RTLD_DEFAULT. См. man 3 dlopen для получения дополнительной информации.
lib = Fiddle::Handle.new
Значение по умолчанию зависит от ОС и предоставляет обработчик для всех уже загруженных библиотек. Например, в большинстве случаев можно использовать его для доступа к libc функциям или к функциям руби, таким как rb_str_new.
static VALUE
rb_fiddle_handle_s_sym(VALUE self, VALUE sym)
{
return fiddle_handle_sym(RTLD_NEXT, 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_eFiddleError, "closed handle");
}
return fiddle_handle_sym(fiddle_handle->ptr, sym);
} Получить адрес как Целое число для функции с именем name.
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_eFiddleError, "%s", dlerror());
#else
rb_raise(rb_eFiddleError, "could not close handle");
#endif
}
return INT2NUM(ret);
}
rb_raise(rb_eFiddleError, "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_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_eFiddleError, "closed handle");
}
return fiddle_handle_sym(fiddle_handle->ptr, sym);
} Получить адрес как Целое число для функции с именем name.
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);
} Возвращает адрес памяти для этого обработчика.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.