Spec-Zone.ru › Ruby 3.4

модуль Fiddle

Обертка libffi для Ruby.

Описание

Fiddle — это расширение для перевода внешнего интерфейса функций (FFI) с ruby.

Он оборачивает libffi, популярную C-библиотеку, которая предоставляет переносимый интерфейс, позволяющий коду, написанному на одном языке, вызывать код, написанный на другом языке.

Пример

Здесь мы будем использовать Fiddle::Function для обертывания floor(3) из libm

require 'fiddle'

libm = Fiddle.dlopen('/lib/libm.so.6')

floor = Fiddle::Function.new(
  libm['floor'],
  [Fiddle::TYPE_DOUBLE],
  Fiddle::TYPE_DOUBLE
)

puts floor.call(3.14159) #=> 3.0

Константы

ALIGN_BOOL

ALIGN_BOOL

Размер выравнивания для bool

ALIGN_CHAR

ALIGN_CHAR

Размер выравнивания для char

ALIGN_DOUBLE

ALIGN_DOUBLE

Размер выравнивания для double

ALIGN_FLOAT

ALIGN_FLOAT

Размер выравнивания для float

ALIGN_INT

ALIGN_INT

Размер выравнивания для int

ALIGN_INT16_T

ALIGN_INT16_T

Размер выравнивания для int16_t

ALIGN_INT32_T

ALIGN_INT32_T

Размер выравнивания для int32_t

ALIGN_INT64_T

ALIGN_INT64_T

Размер выравнивания для int64_t

ALIGN_INT8_T

ALIGN_INT8_T

Размер выравнивания для int8_t

ALIGN_INTPTR_T

ALIGN_INTPTR_T

Размер выравнивания для intptr_t

ALIGN_LONG

ALIGN_LONG

Размер выравнивания для long

ALIGN_LONG_LONG

ALIGN_LONG_LONG

Размер выравнивания для long long

ALIGN_PTRDIFF_T

ALIGN_PTRDIFF_T

Размер выравнивания для ptrdiff_t

ALIGN_SHORT

ALIGN_SHORT

Размер выравнивания для short

ALIGN_SIZE_T

ALIGN_SIZE_T

Размер выравнивания для size_t

ALIGN_SSIZE_T

ALIGN_SSIZE_T

Размер выравнивания для ssize_t

ALIGN_UINTPTR_T

ALIGN_UINTPTR_T

Размер выравнивания для uintptr_t

ALIGN_VOIDP

ALIGN_VOIDP

Размер выравнивания для void*

BUILD_RUBY_PLATFORM

BUILD_RUBY_PLATFORM

Платформа, для которой был скомпилирован Ruby (например, “x86_64-linux” и т.д.)

См. также RUBY_PLATFORM

NULL
Qfalse

Qfalse

Значение Qfalse

Qnil

Qnil

Значение Qnil

Qtrue

Qtrue

Значение Qtrue

Qundef

Qundef

Значение Qundef

RUBY_FREE

RUBY_FREE

Адрес функции ruby_xfree()

SIZEOF_BOOL

SIZEOF_BOOL

размер bool

SIZEOF_CHAR

SIZEOF_CHAR

размер char

SIZEOF_CONST_STRING

SIZEOF_CONST_STRING

размер const char*

SIZEOF_DOUBLE

SIZEOF_DOUBLE

размер double

SIZEOF_FLOAT

SIZEOF_FLOAT

размер float

SIZEOF_INT

SIZEOF_INT

размер int

SIZEOF_INT16_T

SIZEOF_INT16_T

размер int16_t

SIZEOF_INT32_T

SIZEOF_INT32_T

размер int32_t

SIZEOF_INT64_T

SIZEOF_INT64_T

размер int64_t

SIZEOF_INT8_T

SIZEOF_INT8_T

размер int8_t

SIZEOF_INTPTR_T

SIZEOF_INTPTR_T

размер intptr_t

SIZEOF_LONG

SIZEOF_LONG

размер long

SIZEOF_LONG_LONG

SIZEOF_LONG_LONG

размер long long

SIZEOF_PTRDIFF_T

SIZEOF_PTRDIFF_T

размер ptrdiff_t

SIZEOF_SHORT

SIZEOF_SHORT

размер short

SIZEOF_SIZE_T

SIZEOF_SIZE_T

размер size_t

SIZEOF_SSIZE_T

SIZEOF_SSIZE_T

размер ssize_t

SIZEOF_UCHAR

SIZEOF_UCHAR

размер unsigned char

SIZEOF_UINT

SIZEOF_UINT

размер unsigned int

SIZEOF_UINT16_T

SIZEOF_UINT16_T

размер uint16_t

SIZEOF_UINT32_T

SIZEOF_UINT32_T

размер uint32_t

SIZEOF_UINT64_T

SIZEOF_UINT64_T

размер uint64_t

SIZEOF_UINT8_T

SIZEOF_UINT8_T

размер uint8_t

SIZEOF_UINTPTR_T

SIZEOF_UINTPTR_T

размер uintptr_t

SIZEOF_ULONG

SIZEOF_ULONG

размер unsigned long

SIZEOF_ULONG_LONG

SIZEOF_ULONG_LONG

размер unsigned long long

SIZEOF_USHORT

SIZEOF_USHORT

размер unsigned short

SIZEOF_VOIDP

SIZEOF_VOIDP

размер void*

VERSION
WINDOWS

Возвращает boolean, указывающий, является ли хост WIN32

Публичные методы класса

dlopen(library) → Fiddle::Handle
Исходный код
# File ext/fiddle/lib/fiddle.rb, line 91
def dlopen library
  begin
    Fiddle::Handle.new(library)
  rescue DLError => error
    case RUBY_PLATFORM
    when /linux/
      case error.message
      when /\A(\/.+?): (?:invalid ELF header|file too short)/
        # This may be a linker script:
        # https://sourceware.org/binutils/docs/ld.html#Scripts
        path = $1
      else
        raise
      end
    else
      raise
    end

    File.open(path) do |input|
      input.each_line do |line|
        case line
        when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/
          # TODO: Should we support multiple files?
          first_input = $1
          if first_input.start_with?("-l")
            first_input = "lib#{first_input[2..-1]}.so"
          end
          return dlopen(first_input)
        end
      end
    end

    # Not found
    raise
  end
end

Создает новый обработчик, который открывает library, и возвращает экземпляр Fiddle::Handle.

Если nil задано для library, используется Fiddle::Handle::DEFAULT, что эквивалентно RTLD_DEFAULT. См. man 3 dlopen для подробной информации.

lib = Fiddle.dlopen(nil)

Значение по умолчанию зависит от ОС и предоставляет дескриптор для всех уже загруженных библиотек. Например, в большинстве случаев вы можете использовать это для доступа к функциям libc, или функциям Ruby, таким как rb_str_new.

См. Fiddle::Handle.new для подробной информации.

dlunwrap(addr)
Исходный код
VALUE
rb_fiddle_ptr2value(VALUE self, VALUE addr)
{
    return (VALUE)NUM2PTR(addr);
}

Возвращает объект Ruby, хранящийся по адресу памяти addr

Пример:

x = Object.new
# => #<Object:0x0000000107c7d870>
Fiddle.dlwrap(x)
# => 4425504880
Fiddle.dlunwrap(_)
# => #<Object:0x0000000107c7d870>
dlwrap(val)
Исходный код
static VALUE
rb_fiddle_value2ptr(VALUE self, VALUE val)
{
    return PTR2NUM((void*)val);
}

Возвращает адрес памяти объекта Ruby, хранящегося по val

Пример:

x = Object.new
# => #<Object:0x0000000107c7d870>
Fiddle.dlwrap(x)
# => 4425504880

В случае, если val не является объектом, выделенным в куче, этот метод вернет значение помеченного указателя.

Пример:

Fiddle.dlwrap(123)
# => 247
free(addr)
Исходный код
VALUE
rb_fiddle_free(VALUE self, VALUE addr)
{
    void *ptr = NUM2PTR(addr);

    ruby_xfree(ptr);
    return Qnil;
}

Освобождает память по адресу addr

last_error ()
Исходный код
# File ext/fiddle/lib/fiddle.rb, line 57
def self.last_error
  if RUBY_ENGINE == 'jruby'
    errno = FFI.errno
    errno == 0 ? nil : errno
  else
    Thread.current[:__FIDDLE_LAST_ERROR__]
  end
end

Возвращает последнюю Error текущего выполняющегося Thread или nil, если таковой нет

last_error= (error)
Исходный код
# File ext/fiddle/lib/fiddle.rb, line 67
def self.last_error= error
  if RUBY_ENGINE == 'jruby'
    FFI.errno = error || 0
  else
    Thread.current[:__DL2_LAST_ERROR__] = error
    Thread.current[:__FIDDLE_LAST_ERROR__] = error
  end
end

Устанавливает последнюю Error текущего выполняющегося Thread в error

malloc(size)
Исходный код
static VALUE
rb_fiddle_malloc(VALUE self, VALUE size)
{
    void *ptr;
    ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size));
    return PTR2NUM(ptr);
}

Выделяет size байт памяти и возвращает целочисленный адрес памяти для выделенной памяти.

realloc(addr, size)
Исходный код
static VALUE
rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size)
{
    void *ptr = NUM2PTR(addr);

    ptr = (void*)ruby_xrealloc(ptr, NUM2SIZET(size));
    return PTR2NUM(ptr);
}

Изменяет размер памяти, выделенной по адресу памяти addr, до size байт. Возвращает адрес памяти перераспределенной памяти, который может отличаться от переданного адреса.

win32_last_error ()
Исходный код
# File ext/fiddle/lib/fiddle.rb, line 16
def self.win32_last_error
  if RUBY_ENGINE == 'jruby'
    errno = FFI.errno
    errno == 0 ? nil : errno
  else
    Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
  end
end

Возвращает последнюю ошибку win32 Error текущего выполняющегося Thread или nil, если таковой нет

win32_last_error= (error)
Исходный код
# File ext/fiddle/lib/fiddle.rb, line 26
def self.win32_last_error= error
  if RUBY_ENGINE == 'jruby'
    FFI.errno = error || 0
  else
    Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
  end
end

Устанавливает последнюю ошибку win32 Error текущего выполняющегося Thread в error

win32_last_socket_error ()
Исходный код
# File ext/fiddle/lib/fiddle.rb, line 36
def self.win32_last_socket_error
  if RUBY_ENGINE == 'jruby'
    errno = FFI.errno
    errno == 0 ? nil : errno
  else
    Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
  end
end

Возвращает последнюю ошибку win32 сокета Error текущего выполняющегося Thread или nil, если таковой нет

win32_last_socket_error= (error)
Исходный код
# File ext/fiddle/lib/fiddle.rb, line 47
def self.win32_last_socket_error= error
  if RUBY_ENGINE == 'jruby'
    FFI.errno = error || 0
  else
    Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
  end
end

Устанавливает последнюю ошибку win32 сокета Error текущего выполняющегося Thread в error

Приватные методы экземпляра

dlopen(library) → Fiddle::Handle
Исходный код
# File ext/fiddle/lib/fiddle.rb, line 91
def dlopen library
  begin
    Fiddle::Handle.new(library)
  rescue DLError => error
    case RUBY_PLATFORM
    when /linux/
      case error.message
      when /\A(\/.+?): (?:invalid ELF header|file too short)/
        # This may be a linker script:
        # https://sourceware.org/binutils/docs/ld.html#Scripts
        path = $1
      else
        raise
      end
    else
      raise
    end

    File.open(path) do |input|
      input.each_line do |line|
        case line
        when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/
          # TODO: Should we support multiple files?
          first_input = $1
          if first_input.start_with?("-l")
            first_input = "lib#{first_input[2..-1]}.so"
          end
          return dlopen(first_input)
        end
      end
    end

    # Not found
    raise
  end
end

Создает новый обработчик, который открывает library, и возвращает экземпляр Fiddle::Handle.

Если nil задано для library, используется Fiddle::Handle::DEFAULT, что эквивалентно RTLD_DEFAULT. См. man 3 dlopen для подробной информации.

lib = Fiddle.dlopen(nil)

Значение по умолчанию зависит от ОС и предоставляет дескриптор для всех уже загруженных библиотек. Например, в большинстве случаев вы можете использовать это для доступа к функциям libc, или функциям Ruby, таким как rb_str_new.

См. Fiddle::Handle.new для подробной информации.

Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API