Class: Fiddle::Handle
Relationships & Source Files | |
Inherits: | Object |
Defined in: | ext/fiddle/handle.c, ext/fiddle/handle.c, lib/fiddle/ffi_backend.rb |
Overview
The Handle
is the manner to access the dynamic library
Example
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
Addresses to symbols
strcpy_addr = @handle['strcpy']
#=> 140062278451968
or
strcpy_addr = @handle.sym('strcpy')
#=> 140062278451968
Constant Summary
-
DEFAULT =
# File 'lib/fiddle/ffi_backend.rb', line 553new
-
NEXT =
A predefined pseudo-handle of RTLD_NEXT
Which will find the next occurrence of a function in the search order after the current library.
predefined_fiddle_handle(RTLD_NEXT)
-
RTLD_GLOBAL =
# File 'lib/fiddle/ffi_backend.rb', line 484FFI::DynamicLibrary::RTLD_GLOBAL
-
RTLD_LAZY =
# File 'lib/fiddle/ffi_backend.rb', line 485FFI::DynamicLibrary::RTLD_LAZY
-
RTLD_NOW =
# File 'lib/fiddle/ffi_backend.rb', line 486FFI::DynamicLibrary::RTLD_NOW
Class Method Summary
Instance Attribute Summary
- #close_enabled? ⇒ Boolean readonly
Instance Method Summary
-
#[](name)
(also: #sym)
Get the address as an Integer for the function named
name
. - #close
- #disable_close
- #enable_close
-
#file_name
Returns the file name of this handle.
-
#new(library = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL)
constructor
Create a new handler that opens
library
withflags
. -
#sym(name)
Alias for #[].
- #sym_defined?(sym) ⇒ Boolean
-
#to_i ⇒ Integer
Returns the memory address for this handle.
-
#to_ptr ⇒ ?
Returns the
Pointer
of this handle.
Constructor Details
.new(libname = nil, flags = RTLD_LAZY | RTLD_GLOBAL) ⇒ Handle
# File '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
#new(library = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL)
Create a new handler that opens library
with flags
.
If no library
is specified or nil
is given, DEFAULT is used, which is the equivalent to RTLD_DEFAULT. See man 3 dlopen
for more.
lib = Fiddle::Handle.new
The default is dependent on OS, and provide a handle for all libraries already loaded. For example, in most cases you can use this to access libc
functions, or ruby functions like rb_str_new
.
# File 'ext/fiddle/handle.c', line 136
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; }
Class Method Details
.[](func)
[ GitHub ]# File 'lib/fiddle/ffi_backend.rb', line 533
def self.[](func) self.sym(func) end
.sym(func)
[ GitHub ]# File 'lib/fiddle/ffi_backend.rb', line 510
def self.sym(func) DEFAULT.sym(func) end
.sym_defined?(func) ⇒ Boolean
# File 'lib/fiddle/ffi_backend.rb', line 522
def self.sym_defined?(func) DEFAULT.sym_defined?(func) end
Instance Attribute Details
#close_enabled? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'lib/fiddle/ffi_backend.rb', line 545
def close_enabled? @enable_close end
Instance Method Details
#[](name) Also known as: #sym
Get the address as an Integer for the function named name
.
# File 'ext/fiddle/handle.c', line 294
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); }
#close
#disable_close
[ GitHub ]# File 'lib/fiddle/ffi_backend.rb', line 549
def disable_close @enable_close = false end
#enable_close
[ GitHub ]# File 'lib/fiddle/ffi_backend.rb', line 541
def enable_close @enable_close = true end
#file_name
Returns the file name of this handle.
# File 'ext/fiddle/handle.c', line 449
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 }
#[](name)
#sym(name)
Alias for #[].
#sym_defined?(sym) ⇒ Boolean
# File 'ext/fiddle/handle.c', line 409
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; } }
#to_i ⇒ Integer
Returns the memory address for this handle.
# File 'ext/fiddle/handle.c', line 262
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); }
#to_ptr ⇒ ?
Returns the Pointer
of this handle.
# File 'ext/fiddle/handle.c', line 276
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); }