Ruby 2.4

Fiddle::Handle

class Fiddle::Handle

Parent:Object

Fiddle :: Handle是访问动态库的方式

Setup

libc_so = "/lib64/libc.so.6" => "/lib64/libc.so.6" @handle = Fiddle::Handle.new(libc_so) => #<Fiddle::Handle:0x00000000d69ef8>

Setup, with flags

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>

See RTLD_LAZY and 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 flag.

由该库定义的符号将可用于随后加载的库的符号解析。

RTLD_LAZY

RTLD_LAZY

rtld Fiddle::Handle flag.

执行延迟绑定。只有在执行引用它们的代码时才解析符号。如果符号从未被引用,那么它永远不会被解析。(惰性绑定仅针对函数引用执行;对于变量的引用总是在加载该库时立即绑定。)

RTLD_NOW

RTLD_NOW

rtld Fiddle::Handle flag.

如果指定了此值或环境变量LD_BIND_NOW设置为非空字符串,则库中的所有未定义符号都将在Fiddle#dlopen返回前解析。如果无法完成,则返回错误。

公共类方法

sym(name) Show source

获取地址作为名为的函数的整数name。该函数通过RTLD_NEXT上的dlsym进行搜索。

请参阅man(3)dlsym()了解更多信息。

static VALUE rb_fiddle_handle_s_sym(VALUE self, VALUE sym) { return fiddle_handle_sym(RTLD_NEXT, sym }

new(library = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL) Show source

创建一个用标志打开库的新处理程序。

如果未指定库或给出nil,则使用DEFAULT,这与RTLD_DEFAULT等效。可参阅 man 3 dlopen。

lib = Fiddle::Handle.new

缺省值取决于操作系统,并为已加载的所有库提供句柄。例如,在大多数情况下,您可以使用它来访问libc函数或ruby函数rb_str_new

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

sym(name) Show source

获取地址作为名为的函数的整数name

static VALUE rb_fiddle_handle_s_sym(VALUE self, VALUE sym) { return fiddle_handle_sym(RTLD_NEXT, sym }

公共实例方法

sym(name) Show source

获取地址作为名为的函数的整数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 }

关闭显示源代码

关闭此句柄。

多次调用关闭会引发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_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_enabled? Show source

如果在处理废物回收时调用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; }

disable_close Show source

当这个句柄被废物收集时,禁用对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; }

enable_close Show source

当这个句柄被废物收集时启用对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; }

sym(name) Show source

获取名称为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 }

to_i Show source

返回此句柄的内存地址。

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 }