123456789_123456789_123456789_123456789_123456789_

Class: FFI::DynamicLibrary

Relationships & Source Files
Namespace Children
Classes:
Inherits: Object
Defined in: ext/ffi_c/DynamicLibrary.c,
lib/ffi/dynamic_library.rb

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(libname, libflags) .new(DynamicLibrary)

[ GitHub ]

  
# File 'ext/ffi_c/DynamicLibrary.c', line 136

static VALUE
library_initialize(VALUE self, VALUE libname, VALUE libflags)
{
    Library* library;
    int flags;

    Check_Type(libflags, T_FIXNUM);

    TypedData_Get_Struct(self, Library, &rbffi_library_data_type, library);
    flags = libflags != Qnil ? NUM2UINT(libflags) : 0;

    library->handle = dl_open(libname != Qnil ? StringValueCStr(libname) : NULL, flags);
    if (library->handle == NULL) {
        char errmsg[1024];
        dl_error(errmsg, sizeof(errmsg));
        rb_raise(rb_eLoadError, "Could not open library '%s': %s",
                libname != Qnil ? StringValueCStr(libname) : "[current process]",
                errmsg);
    }
#ifdef __CYGWIN__
    // On Cygwin 1.7.17 "dlsym(dlopen(0,0), 'getpid')" fails. (dlerror: "No such process")
    // As a workaround we can use "dlsym(RTLD_DEFAULT, 'getpid')" instead.
    // Since 0 == RTLD_DEFAULT we won't call dl_close later.
    if (libname == Qnil) {
        dl_close(library->handle);
        library->handle = RTLD_DEFAULT;
    }
#endif
    rb_iv_set(self, "@name", libname != Qnil ? rb_str_new_frozen(libname) : rb_str_new2("[current process]"));

    rb_obj_freeze(self);
    return self;
}

Class Method Details

#last_error Also known as: #last_error

[ GitHub ]

  
# File 'ext/ffi_c/DynamicLibrary.c', line 187

static VALUE
library_dlerror(VALUE self)
{
    char errmsg[1024];
    dl_error(errmsg, sizeof(errmsg));
    return rb_str_new2(errmsg);
}

.load_library(name, flags) (private)

[ GitHub ]

  
# File 'lib/ffi/dynamic_library.rb', line 69

def self.load_library(name, flags)
  if name == FFI::CURRENT_PROCESS
    FFI::DynamicLibrary.open(nil, RTLD_LAZY | RTLD_LOCAL)
  else
    flags ||= RTLD_LAZY | RTLD_LOCAL

    libnames = (name.is_a?(::Array) ? name : [name])
    libnames = libnames.map(&:to_s).map { |n| [n, FFI.map_library_name(n)].uniq }.flatten.compact
    errors = []

    libnames.each do |libname|
      lib = try_load(libname, flags, errors)
      return lib if lib

      unless libname.start_with?("/")
        SEARCH_PATH.each do |prefix|
          path = "#{prefix}/#{libname}"
          if File.exist?(path)
            lib = try_load(path, flags, errors)
            return lib if lib
          end
        end
      end
    end

    raise LoadError, [*errors, SEARCH_PATH_MESSAGE].join(".\n")
  end
end

.open(libname, libflags) .a(library)

[ GitHub ]

  
# File 'ext/ffi_c/DynamicLibrary.c', line 122

static VALUE
library_open(VALUE klass, VALUE libname, VALUE libflags)
{
    return library_initialize(library_allocate(klass), libname, libflags);
}

.try_load(libname, flags, errors) (private)

[ GitHub ]

  
# File 'lib/ffi/dynamic_library.rb', line 99

def self.try_load(libname, flags, errors)
  begin
    lib = FFI::DynamicLibrary.open(libname, flags)
    return lib if lib

  # LoadError for C ext & JRuby, RuntimeError for TruffleRuby
  rescue LoadError, RuntimeError => ex
    if ex.message =~ /(([^ \t()])+\.so([^ \t:()])*):([ \t])*(invalid ELF header|file too short|invalid file format)/
      if File.binread($1) =~ /(?:GROUP|INPUT) *\( *([^ \)]+)/
        return try_load($1, flags, errors)
      end
    end

    errors << ex
    nil
  end
end

Instance Attribute Details

#name (readonly)

[ GitHub ]

Instance Method Details

#find_symbol(name) #find_function(name)

Alias for #find_symbol.

#find_symbol(name) Also known as: #find_function, #find_variable

[ GitHub ]

  
# File 'ext/ffi_c/DynamicLibrary.c', line 170

static VALUE
library_dlsym(VALUE self, VALUE name)
{
    Library* library;
    void* address = NULL;
    Check_Type(name, T_STRING);

    TypedData_Get_Struct(self, Library, &rbffi_library_data_type, library);
    address = dl_sym(library->handle, StringValueCStr(name));

    return address != NULL ? symbol_new(self, address, name) : Qnil;
}

#find_symbol(name) #find_variable(name)

Alias for #find_symbol.

#last_error #last_error

Alias for .last_error.