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 576new -
NEXT =
# File 'ext/fiddle/handle.c', line 536
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 507FFI::DynamicLibrary::RTLD_GLOBAL
-
RTLD_LAZY =
# File 'lib/fiddle/ffi_backend.rb', line 508FFI::DynamicLibrary::RTLD_LAZY
-
RTLD_NOW =
# File 'lib/fiddle/ffi_backend.rb', line 509FFI::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
librarywithflags. -
#sym(name)
Alias for #[].
- #sym_defined?(sym) ⇒ Boolean
-
#to_i ⇒ Integer
Returns the memory address for this handle.
-
#to_ptr ⇒ ?
Returns the
Pointerof this handle.
Constructor Details
.new(libname = nil, flags = RTLD_LAZY | RTLD_GLOBAL) ⇒ Handle
# File 'lib/fiddle/ffi_backend.rb', line 511
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 556
def self.[](func) self.sym(func) end
.sym(func)
[ GitHub ]# File 'lib/fiddle/ffi_backend.rb', line 533
def self.sym(func) DEFAULT.sym(func) end
.sym_defined?(func) ⇒ Boolean
# File 'lib/fiddle/ffi_backend.rb', line 545
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 568
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 572
def disable_close @enable_close = false end
#enable_close
[ GitHub ]# File 'lib/fiddle/ffi_backend.rb', line 564
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);
}