类 Fiddle::Handle
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
返回之前将解析库中的所有未定义符号。如果无法完成此操作,则会返回错误。
公共类方法
获取名为 name
的函数的地址作为 Integer
。该函数通过 dlsym 在 RTLD_NEXT 上进行搜索。
有关更多信息,请参见 man(3) dlsym()。
static VALUE rb_fiddle_handle_s_sym(VALUE self, VALUE sym) { return fiddle_handle_sym(RTLD_NEXT, sym); }
创建一个新的处理程序,使用 flags
打开 library
。
如果未指定 library
或给定 nil
,则使用 DEFAULT
,它等效于 RTLD_DEFAULT。有关详细信息,请参见 man 3 dlopen
。
lib = Fiddle::Handle.new
默认值取决于操作系统,并为已加载的所有库提供句柄。例如,在大多数情况下,你可以使用它来访问 libc
函数或 rb_str_new
等 Ruby 函数。
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; }
以 Integer
的形式获取名为 name
的函数的地址。
static VALUE rb_fiddle_handle_s_sym(VALUE self, VALUE sym) { return fiddle_handle_sym(RTLD_NEXT, sym); }
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; } }
公共实例方法
关闭此句柄。
多次调用 close 将引发 Fiddle::DLError
异常。
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; }
如果在垃圾回收此句柄时将调用 dlclose(),则返回 true
。
有关详细信息,请参见 man(3) dlclose()。
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; }
在垃圾回收此句柄时禁用对 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; }
返回此句柄的文件名。
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 }
以 Integer
的形式获取名为 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); }
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); }
返回此句柄的 Fiddle::Pointer
。
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); }