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
Methods
#
C
D
E
N
S
T
Constants
NEXT = Document-const
 

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.

DEFAULT = Document-const
 

DEFAULT

A predefined pseudo-handle of RTLD_DEFAULT

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

Class Public methods
sym(name)

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)

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 : StringValuePtr(lib);
        cflag = RTLD_LAZY | RTLD_GLOBAL;
        break;
      case 2:
        clib = NIL_P(lib) ? NULL : StringValuePtr(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)
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));
}
Instance Public methods
sym(name)

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

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

    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, StringValueCStr(sym));
}
close

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?

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

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

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

    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, StringValueCStr(sym));
}
to_i

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