Spec-Zone.ru › Ruby 3.4
  1. Fiddle::
  2. Указатель

class Fiddle::Pointer

Родительский класс:
Object

Fiddle::Pointer — это класс для работы с указателями C

Атрибуты

ffi_ptr [R]

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

[] (value)

Получает базовый указатель для объекта Ruby val и возвращает его как объект Fiddle::Pointer.

Псевдоним для: to_ptr
from_native (value, ctx) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 236
def self.from_native(value, ctx)
  self.new(value)
end
malloc (size, free = nil) { |pointer| ... } Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 338
def self.malloc(size, free = nil)
  if block_given? and free.nil?
    message = "a free function must be supplied to #{self}.malloc " +
              "when it is called with a block"
    raise ArgumentError, message
  end

  pointer = new(LibC.malloc(size), size, free)
  if block_given?
    begin
      yield(pointer)
    ensure
      pointer.call_free
    end
  else
    pointer
  end
end

Примеры

# Automatically freeing the pointer when the block is exited - recommended
Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) do |pointer|
  ...
end

# Manually freeing but relying on the garbage collector otherwise
pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
...
pointer.call_free

# Relying on the garbage collector - may lead to unlimited memory allocated before freeing any, but safe
pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
...

# Only manually freeing
pointer = Fiddle::Pointer.malloc(size)
begin
  ...
ensure
  Fiddle.free pointer
end

# No free function and no call to free - the native memory will leak if the pointer is garbage collected
pointer = Fiddle::Pointer.malloc(size)
...

Выделяет size байт памяти и связывает их с необязательным freefunc.

Если передан блок, указатель будет передан ему вместо возврата, а возвращено будет значение блока. Если передан блок, необходимо указать freefunc.

Если передан freefunc, он будет вызван один раз — когда указатель будет собран сборщиком мусора, при выходе из блока (если блок передан) или при вызове пользователем call_free, в зависимости от того, что произойдёт раньше. freefunc должен быть адресом, указывающим на функцию, или экземпляром Fiddle::Function.

new (addr, size = nil, free = nil) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 300
def initialize(addr, size = nil, free = nil)
  ptr = if addr.is_a?(FFI::Pointer)
          addr

        elsif addr.is_a?(Integer)
          FFI::Pointer.new(addr)

        elsif addr.respond_to?(:to_ptr)
          fiddle_ptr = addr.to_ptr
          if fiddle_ptr.is_a?(Pointer)
            fiddle_ptr.ffi_ptr
          elsif fiddle_ptr.is_a?(FFI::AutoPointer)
            addr.ffi_ptr
          elsif fiddle_ptr.is_a?(FFI::Pointer)
            fiddle_ptr
          else
            raise DLError.new("to_ptr should return a Fiddle::Pointer object, was #{fiddle_ptr.class}")
          end
        elsif addr.is_a?(IO)
          raise NotImplementedError, "IO ptr isn't supported"
        else
          FFI::Pointer.new(Integer(addr))
        end

  @size = size ? size : ptr.size
  @free = free
  @ffi_ptr = ptr
  @freed = false
end
Fiddle::Pointer.new(address) → fiddle_cptr Показать исходный код
new(address, size) → fiddle_cptr
new(address, size, freefunc) → fiddle_cptr
static VALUE
rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self)
{
    VALUE ptr, sym, size, wrap = 0, funcwrap = 0;
    struct ptr_data *data;
    void *p = NULL;
    freefunc_t f = NULL;
    long s = 0;

    if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) {
        VALUE addrnum = rb_Integer(ptr);
        if (addrnum != ptr) wrap = ptr;
        p = NUM2PTR(addrnum);
    }
    if (argc >= 2) {
        s = NUM2LONG(size);
    }
    if (argc >= 3) {
        f = get_freefunc(sym, &funcwrap);
    }

    if (p) {
        TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
        if (data->ptr && data->free) {
            /* Free previous memory. Use of inappropriate initialize may cause SEGV. */
            (*(data->free))(data->ptr);
        }
        RB_OBJ_WRITE(self, &data->wrap[0], wrap);
        RB_OBJ_WRITE(self, &data->wrap[1], funcwrap);
        data->ptr  = p;
        data->size = s;
        data->free = f;
    }

    return Qnil;
}

Создаёт новый указатель на address с необязательными size и freefunc.

freefunc будет вызван при сборке экземпляра сборщиком мусора.

read (addr, len) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 269
def self.read(addr, len)
  FFI::Pointer.new(addr).read_bytes(len)
end

Или считывает память по адресу address длиной len и возвращает строку с содержимым этой памяти

to_native (value, ctx) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 224
def self.to_native(value, ctx)
  if value.is_a?(Pointer)
    value.ffi_ptr

  elsif value.is_a?(Integer)
    FFI::Pointer.new(value)

  elsif value.is_a?(String)
    value
  end
end
to_ptr (value) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 240
def self.to_ptr(value)
  if value.is_a?(String)
    cptr = Pointer.malloc(value.bytesize)
    cptr.ffi_ptr.put_string(0, value)
    cptr

  elsif value.is_a?(Array)
    raise NotImplementedError, "array ptr"

  elsif value.respond_to?(:to_ptr)
    ptr = value.to_ptr
    case ptr
    when Pointer
      ptr
    when FFI::Pointer
      Pointer.new(ptr)
    else
      raise DLError.new("to_ptr should return a Fiddle::Pointer object, was #{ptr.class}")
    end

  else
    Pointer.new(value)
  end
end

Получает базовый указатель для объекта Ruby val и возвращает его как объект Fiddle::Pointer.

Также имеет псевдоним: []
write (addr, bytes) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 265
def self.write(addr, bytes)
  FFI::Pointer.new(addr).write_bytes(bytes)
end

Записывает байты из str в область памяти, на которую указывает address.

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

+ (delta) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 440
def +(delta)
  self.class.new(to_i + delta, @size - delta)
end

Возвращает новый экземпляр указателя, смещённый вперёд на n байт.

+@ () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 468
def +@
  ptr
end

Возвращает новый экземпляр Fiddle::Pointer, представляющий собой разыменованный указатель для этого указателя.

Аналог оператора звёздочки в C.

- (delta) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 444
def -(delta)
  self.class.new(to_i - delta, @size + delta)
end

Возвращает новый экземпляр указателя, смещённый назад на n байт.

-@ () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 472
def -@
  ref
end

Возвращает новый экземпляр Fiddle::Pointer, представляющий собой указатель-ссылку на этот указатель.

Аналог оператора амперсанда в C.

<=> (other) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 448
def <=>(other)
  return unless other.is_a?(Pointer)
  diff = self.to_i - other.to_i
  return 0 if diff == 0
  diff > 0 ? 1 : -1
end

Возвращает -1, если значение меньше, 0, если равно, и 1, если больше other.

Возвращает nil, если ptr нельзя сравнить с other.

== (other) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 460
def ==(other)
  eql?(other)
end

Возвращает true, если other содержит тот же указатель, и false в противном случае.

[] (index, length = nil) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 396
def [](index, length = nil)
  if length
    ffi_ptr.get_bytes(index, length)
  else
    ffi_ptr.get_char(index)
  end
rescue FFI::NullPointerError
  raise DLError.new("NULL pointer dereference")
end

Возвращает целое число, хранящееся по индексу index.

Если указаны start и length, будет возвращена строка, содержащая байты длиной length, начиная с start.

[]= (*args, value) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 277
def []=(*args, value)
  if args.size == 2
    if value.is_a?(Integer)
      value = self.class.new(value)
    end
    if value.is_a?(Fiddle::Pointer)
      value = value.to_str(args[1])
    end

    @ffi_ptr.put_bytes(args[0], value, 0, args[1])
  elsif args.size == 1
    if value.is_a?(Fiddle::Pointer)
      value = value.to_str(args[0] + 1)
    else
      value = value.chr
    end

    @ffi_ptr.put_bytes(args[0], value, 0, 1)
  end
rescue FFI::NullPointerError
  raise DLError.new("NULL pointer access")
end

Устанавливает значение index равным int.

Или записывает в память по адресу start до length содержимое string, данные из памяти dl_cptr или данные по адресу памяти addr.

call_free () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 377
def call_free
  return if @free.nil?
  return if @freed
  if @free == RUBY_FREE
    LibC::FREE.call(@ffi_ptr)
  else
    @free.call(@ffi_ptr)
  end
  @freed = true
end

Вызывает функцию освобождения для этого указателя. Повторный вызов ничего не делает. Если функция освобождения не назначена, метод ничего не делает.

eql? (other) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 455
def eql?(other)
  return unless other.is_a?(Pointer)
  self.to_i == other.to_i
end

Возвращает true, если other содержит тот же указатель, и false в противном случае.

free () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 369
def free
  @free
end

Получает функцию освобождения для этого указателя.

Возвращает новый экземпляр Fiddle::Function.

См. Fiddle::Function.new

free= (free) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 373
def free=(free)
  @free = free
end

Назначает для этого указателя функцию освобождения function в указанном объекте Fiddle::Function.

freed? () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 388
def freed?
  @freed
end

Возвращает информацию о том, была ли вызвана функция освобождения для этого указателя.

inspect () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 436
def inspect
  "#<#{self.class.name} ptr=#{to_i.to_s(16)} size=#{@size} free=#{@free.inspect}>"
end

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

null? () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 357
def null?
  @ffi_ptr.null?
end

Возвращает true, если это нулевой указатель.

ptr () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 464
def ptr
  Pointer.new(ffi_ptr.get_pointer(0))
end

Возвращает новый экземпляр Fiddle::Pointer, представляющий собой разыменованный указатель для этого указателя.

Аналог оператора звёздочки в C.

ref () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 476
def ref
  cptr = Pointer.malloc(FFI::Type::POINTER.size, RUBY_FREE)
  cptr.ffi_ptr.put_pointer(0, ffi_ptr)
  cptr
end

Возвращает новый экземпляр Fiddle::Pointer, представляющий собой указатель-ссылку на этот указатель.

Аналог оператора амперсанда в C.

size () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 365
def size
  defined?(@layout) ? @layout.size : @size
end

Получает размер этого указателя.

size= (size) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 392
def size=(size)
  @size = size
end

Устанавливает размер этого указателя равным size

to_i () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 406
def to_i
  ffi_ptr.to_i
end

Возвращает целочисленный адрес памяти этого указателя.

Также имеет псевдоним: to_int
to_int ()

Возвращает целочисленный адрес памяти этого указателя.

Псевдоним для: to_i
to_ptr () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 361
def to_ptr
  @ffi_ptr
end
to_s (len = nil) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 412
def to_s(len = nil)
  if len
    ffi_ptr.get_string(0, len)
  else
    ffi_ptr.get_string(0)
  end
rescue FFI::NullPointerError
  raise DLError.new("NULL pointer access")
end

без 0

to_str (len = nil) Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 422
def to_str(len = nil)
  if len
    ffi_ptr.read_string(len)
  else
    ffi_ptr.read_string(@size)
  end
rescue FFI::NullPointerError
  raise DLError.new("NULL pointer access")
end
ptr.to_str        => string
ptr.to_str(len)   => string

Возвращает содержимое указателя в виде строки.

При вызове без аргументов этот метод возвращает содержимое длиной size этого указателя.

При вызове с len будет возвращена строка длиной len байт.

См. to_s

to_value () Показать исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 432
def to_value
  raise NotImplementedError, "to_value isn't supported"
end

Преобразует этот указатель в объект Ruby.

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

Spec-Zone.ru

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