class Fiddle::Pointer - Documentation for Ruby 3.4
Description: class Fiddle::Pointer: Fiddle::Pointer is a class to handle C pointers
Keywords: ruby,class,Fiddle::Pointer

# class Fiddle::Pointer

`Fiddle::Pointer` is a class to handle C pointers

### Attributes

ffi_ptr [R]

### Public Class Methods

[] (value)

Get the underlying pointer for ruby object `val` and return it as a `Fiddle::Pointer` object.

Alias for: to_ptr
from_native (value, ctx)
Source

    # 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| ... }
Source

    # 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

## Examples¶ ↑

    # 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)
    ...

Allocate `size` bytes of memory and associate it with an optional `freefunc`.

If a block is supplied, the pointer will be yielded to the block instead of being returned, and the return value of the block will be returned. A `freefunc` must be supplied if a block is.

If a `freefunc` is supplied it will be called once, when the pointer is garbage collected or when the block is left if a block is supplied or when the user calls `call_free`, whichever happens first. `freefunc` must be an address pointing to a function or an instance of `Fiddle::Function`.

new (addr, size = nil, free = nil)
Source

    # 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
Source

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

Create a new pointer to `address` with an optional `size` and `freefunc`.

`freefunc` will be called when the instance is garbage collected.

read (addr, len)
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 269
    def self.read(addr, len)
      FFI::Pointer.new(addr).read_bytes(len)
    end

Or read the memory at address `address` with length `len` and return a string with that memory

to_native (value, ctx)
Source

    # 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)
Source

    # 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

Get the underlying pointer for ruby object `val` and return it as a `Fiddle::Pointer` object.

Also aliased as: []
write (addr, bytes)
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 265
    def self.write(addr, bytes)
      FFI::Pointer.new(addr).write_bytes(bytes)
    end

Write bytes in `str` to the location pointed to by `address`.

### Public Instance Methods

+ (delta)
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 440
    def +(delta)
      self.class.new(to_i + delta, @size - delta)
    end

Returns a new pointer instance that has been advanced `n` bytes.

+@ ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 468
    def +@
      ptr
    end

Returns a new `Fiddle::Pointer` instance that is a dereferenced pointer for this pointer.

Analogous to the star operator in C.

- (delta)
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 444
    def -(delta)
      self.class.new(to_i - delta, @size + delta)
    end

Returns a new pointer instance that has been moved back `n` bytes.

-@ ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 472
    def -@
      ref
    end

Returns a new `Fiddle::Pointer` instance that is a reference pointer for this pointer.

Analogous to the ampersand operator in C.

<=> (other)
Source

    # 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

Returns -1 if less than, 0 if equal to, 1 if greater than `other`.

Returns nil if `ptr` cannot be compared to `other`.

== (other)
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 460
    def ==(other)
      eql?(other)
    end

Returns true if `other` wraps the same pointer, otherwise returns false.

[] (index, length = nil)
Source

    # 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

Returns integer stored at index.

If start and length are given, a string containing the bytes from start of length will be returned.

[]= (*args, value)
Source

    # 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

Set the value at `index` to `int`.

Or, set the memory at `start` until `length` with the contents of `string`, the memory from `dl_cptr`, or the memory pointed at by the memory address `addr`.

call_free ()
Source

    # 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

Call the free function for this pointer. Calling more than once will do nothing. Does nothing if there is no free function attached.

eql? (other)
Source

    # 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

Returns true if `other` wraps the same pointer, otherwise returns false.

free ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 369
    def free
      @free
    end

Get the free function for this pointer.

Returns a new instance of `Fiddle::Function`.

See `Fiddle::Function.new`

free= (free)
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 373
    def free=(free)
      @free = free
    end

Set the free function for this pointer to `function` in the given `Fiddle::Function`.

freed? ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 388
    def freed?
      @freed
    end

Returns if the free function for this pointer has been called.

inspect ()
Source

    # 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

Returns a string formatted with an easily readable representation of the internal state of the pointer.

null? ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 357
    def null?
      @ffi_ptr.null?
    end

Returns `true` if this is a null pointer.

ptr ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 464
    def ptr
      Pointer.new(ffi_ptr.get_pointer(0))
    end

Returns a new `Fiddle::Pointer` instance that is a dereferenced pointer for this pointer.

Analogous to the star operator in C.

ref ()
Source

    # 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

Returns a new `Fiddle::Pointer` instance that is a reference pointer for this pointer.

Analogous to the ampersand operator in C.

size ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 365
    def size
      defined?(@layout) ? @layout.size : @size
    end

Get the size of this pointer.

size= (size)
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 392
    def size=(size)
      @size = size
    end

Set the size of this pointer to `size`

to_i ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 406
    def to_i
      ffi_ptr.to_i
    end

Returns the integer memory location of this pointer.

Also aliased as: to_int
to_int ()

Returns the integer memory location of this pointer.

Alias for: to_i
to_ptr ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 361
    def to_ptr
      @ffi_ptr
    end

to_s (len = nil)
Source

    # 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

without 0

to_str (len = nil)
Source

    # 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

Returns the pointer contents as a string.

When called with no arguments, this method will return the contents with the length of this pointer’s `size`.

When called with `len`, a string of `len` bytes will be returned.

See `to_s`

to_value ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 432
    def to_value
      raise NotImplementedError, "to_value isn't supported"
    end

Cast this pointer to a ruby object.