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