класс 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.
Если библиотека не указана или nil задано, используется DEFAULT, что эквивалентно RTLD_DEFAULT. Смотрите man 3 dlopen для получения дополнительной информации.
lib = Fiddle::Handle.new
Значение по умолчанию зависит от ОС и предоставляет обработчик для всех уже загруженных библиотек. Например, в большинстве случаев вы можете использовать это для доступа к libc функциям или функциям Ruby, таким как rb_str_new.
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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.