class DL::Handle

The DL::Handle is the manner to access the dynamic library

Example

Setup

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

Setup, with flags

libc_so = "/lib64/libc.so.6"
=> "/lib64/libc.so.6"
@handle = DL::Handle.new(libc_so, DL::RTLD_LAZY | DL::RTLD_GLOBAL)
=> #<DL::Handle:0x00000000d69ef8>

Addresses to symbols

strcpy_addr = @handle['strcpy']
=> 140062278451968

or

strcpy_addr = @handle.sym('strcpy')
=> 140062278451968

Constants

DEFAULT

DEFAULT

A predefined pseudo-handle of RTLD_DEFAULT

Which will find the first occurrence of the desired symbol using the default library search order

NEXT

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.

Public Class Methods

sym(name) click to toggle source

Get the address as an Integer for the function named name.

VALUE
rb_dlhandle_s_sym(VALUE self, VALUE sym)
{
    return dlhandle_sym(RTLD_NEXT, StringValueCStr(sym));
}
initialize(lib = nil, flags = DL::RTLD_LAZY | DL::RTLD_GLOBAL) click to toggle source

Create a new handler that opens library named lib with flags. If no library is specified, RTLD_DEFAULT is used.

VALUE
rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
{
    void *ptr;
    struct dl_handle *dlhandle;
    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 : SafeStringValuePtr(lib);
        cflag = RTLD_LAZY | RTLD_GLOBAL;
        break;
      case 2:
        clib = NIL_P(lib) ? NULL : SafeStringValuePtr(lib);
        cflag = NUM2INT(flag);
        break;
      default:
        rb_bug("rb_dlhandle_new");
    }

    rb_secure(2);

#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
        ptr = w32_coredll();
# endif
    }
    else
#endif
        ptr = dlopen(clib, cflag);
#if defined(HAVE_DLERROR)
    if( !ptr && (err = dlerror()) ){
        rb_raise(rb_eDLError, "%s", err);
    }
#else
    if( !ptr ){
        err = dlerror();
        rb_raise(rb_eDLError, "%s", err);
    }
#endif
    TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
    if( dlhandle->ptr && dlhandle->open && dlhandle->enable_close ){
        dlclose(dlhandle->ptr);
    }
    dlhandle->ptr = ptr;
    dlhandle->open = 1;
    dlhandle->enable_close = 0;

    if( rb_block_given_p() ){
        rb_ensure(rb_yield, self, rb_dlhandle_close, self);
    }

    return Qnil;
}
sym(name) click to toggle source
Document-method: []

Get the address as an Integer for the function named name.

VALUE
rb_dlhandle_s_sym(VALUE self, VALUE sym)
{
    return dlhandle_sym(RTLD_NEXT, StringValueCStr(sym));
}

Public Instance Methods

sym(name) click to toggle source

Get the address as an Integer for the function named name.

VALUE
rb_dlhandle_sym(VALUE self, VALUE sym)
{
    struct dl_handle *dlhandle;
    const char *name;

    name = SafeStringValuePtr(sym);

    TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
    if( ! dlhandle->open ){
        rb_raise(rb_eDLError, "closed handle");
    }

    return dlhandle_sym(dlhandle->ptr, name);
}
close click to toggle source

Close this DL::Handle. Calling close more than once will raise a DL::DLError exception.

VALUE
rb_dlhandle_close(VALUE self)
{
    struct dl_handle *dlhandle;

    TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
    if(dlhandle->open) {
        int ret = dlclose(dlhandle->ptr);
        dlhandle->open = 0;

        /* Check dlclose for successful return value */
        if(ret) {
#if defined(HAVE_DLERROR)
            rb_raise(rb_eDLError, "%s", dlerror());
#else
            rb_raise(rb_eDLError, "could not close handle");
#endif
        }
        return INT2NUM(ret);
    }
    rb_raise(rb_eDLError, "dlclose() called too many times");

    UNREACHABLE;
}
close_enabled? click to toggle source

Returns true if dlclose() will be called when this DL::Handle is garbage collected.

static VALUE
rb_dlhandle_close_enabled_p(VALUE self)
{
    struct dl_handle *dlhandle;

    TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);

    if(dlhandle->enable_close) return Qtrue;
    return Qfalse;
}
disable_close click to toggle source

Disable a call to dlclose() when this DL::Handle is garbage collected.

VALUE
rb_dlhandle_disable_close(VALUE self)
{
    struct dl_handle *dlhandle;

    TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
    dlhandle->enable_close = 0;
    return Qnil;
}
enable_close click to toggle source

Enable a call to dlclose() when this DL::Handle is garbage collected.

VALUE
rb_dlhandle_enable_close(VALUE self)
{
    struct dl_handle *dlhandle;

    TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
    dlhandle->enable_close = 1;
    return Qnil;
}
sym(name) click to toggle source
Document-method: []

Get the address as an Integer for the function named name.

VALUE
rb_dlhandle_sym(VALUE self, VALUE sym)
{
    struct dl_handle *dlhandle;
    const char *name;

    name = SafeStringValuePtr(sym);

    TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
    if( ! dlhandle->open ){
        rb_raise(rb_eDLError, "closed handle");
    }

    return dlhandle_sym(dlhandle->ptr, name);
}
to_i click to toggle source

Returns the memory address for this handle.

VALUE
rb_dlhandle_to_i(VALUE self)
{
    struct dl_handle *dlhandle;

    TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
    return PTR2NUM(dlhandle);
}