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']
#=> 140062278451968or
strcpy_addr = @handle.sym('strcpy')
#=> 140062278451968Constant Summary
- 
    DEFAULT =
    
 # File 'lib/fiddle/ffi_backend.rb', line 576new
- 
    NEXT =
    # File 'ext/fiddle/handle.c', line 536A 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.newThe 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);
}