Class: FFI::Pointer

### Home Classes Methods

### In Files

- lib/ffi/pointer.rb
- ext/ffi_c/ffi.c

### Parent

FFI::AbstractMemory

### Methods

- ::new
- ::size
- #+
- #==
- #address
- #autorelease=
- #autorelease?
- #free
- #initialize_copy
- #inspect
- #null?
- #order
- #read_array_of_type
- #read_string
- #read_string_length
- #read_string_to_null
- #slice
- #to_i
- #to_s
- #type_size
- #write_array_of_type
- #write_string
- #write_string_length

### Files

- Makefile
- LICENSE
- compile
- configure
- depcomp
- stamp-vti
- install-sh
- libtool-version
- mdate-sh
- missing

### Class/Module Index

Quicksearch

- FFI
- FFI::AutoPointer
- FFI::AutoPointer::CallableReleaser
- FFI::AutoPointer::DefaultReleaser
- FFI::AutoPointer::Releaser
- FFI::ConstGenerator
- FFI::ConstGenerator::Constant
- FFI::Enum
- FFI::Enums
- FFI::Function
- FFI::FunctionType
- FFI::Generator
- FFI::Generator::Task
- FFI::IO
- FFI::LastError
- FFI::ManagedStruct
- FFI::MemoryPointer
- FFI::NativeType
- FFI::Platform
- FFI::PlatformError
- FFI::Pointer
- FFI::StrPtrConverter
- FFI::Struct
- FFI::Struct::InlineArray
- FFI::Struct::ManagedStructConverter
- FFI::StructByReference
- FFI::StructByValue
- FFI::StructGenerator
- FFI::StructGenerator::Field
- FFI::StructLayout
- FFI::StructLayout::Array
- FFI::StructLayout::Enum
- FFI::StructLayout::Field
- FFI::StructLayout::Function
- FFI::StructLayout::InnerStruct
- FFI::StructLayout::Mapped
- FFI::StructLayout::Number
- FFI::StructLayout::Pointer
- FFI::StructLayout::String
- FFI::StructLayoutBuilder
- FFI::Type
- FFI::Type::Builtin
- FFI::TypesGenerator
- FFI::Union
- FFI::VariadicInvoker

No matching classes.

# FFI::Pointer

Pointer class is used to manage C pointers with ease. A {Pointer} object is defined by his {address} (as a C pointer). It permits additions with an integer for pointer arithmetic.

## Autorelease

A pointer object may autorelease his contents when freed (by default). This behaviour may be changed with {autorelease=} method.

### Constants

NULL

  NULL pointer

SIZE

  Pointer size

### Public Class Methods

new(p1, p2 = v2) click to toggle source

@overload initialize(pointer)

    @param [Pointer] pointer another pointer to initialize from
    Create a new pointer from another {Pointer}.

@overload initialize(type, address)

    @param [Type] type type for pointer
    @param [Integer] address base address for pointer
    Create a new pointer from a {Type} and a base adresse

@return [self] A new instance of Pointer.

    static VALUE
    ptr_initialize(int argc, VALUE* argv, VALUE self)
    {
        Pointer* p;
        VALUE rbType = Qnil, rbAddress = Qnil;
        int typeSize = 1;

        Data_Get_Struct(self, Pointer, p);

        switch (rb_scan_args(argc, argv, "11", &rbType, &rbAddress)) {
            case 1:
                rbAddress = rbType;
                typeSize = 1;
                break;
            case 2:
                typeSize = rbffi_type_size(rbType);
                break;
            default:
                rb_raise(rb_eArgError, "Invalid arguments");
        }

        switch (TYPE(rbAddress)) {
            case T_FIXNUM:
            case T_BIGNUM:
                p->memory.address = (void*) (uintptr_t) NUM2LL(rbAddress);
                p->memory.size = LONG_MAX;
                if (p->memory.address == NULL) {
                    p->memory.flags = 0;
                }
                break;

            default:
                if (rb_obj_is_kind_of(rbAddress, rbffi_PointerClass)) {
                    Pointer* orig;

                    p->rbParent = rbAddress;
                    Data_Get_Struct(rbAddress, Pointer, orig);
                    p->memory = orig->memory;
                } else {
                    rb_raise(rb_eTypeError, "wrong argument type, expected Integer or FFI::Pointer");
                }
                break;
        }

        p->memory.typeSize = typeSize;

        return self;
    }

size() click to toggle source

Return the size of a pointer on the current platform, in bytes @return [Numeric]

    # File lib/ffi/pointer.rb, line 30
    def self.size
      SIZE
    end

### Public Instance Methods

ptr + offset click to toggle source
@param [Numeric] offset
@return [Pointer]
Return a new {Pointer} from an existing pointer and an +offset+.

    static VALUE
    ptr_plus(VALUE self, VALUE offset)
    {
        AbstractMemory* ptr;
        long off = NUM2LONG(offset);

        Data_Get_Struct(self, AbstractMemory, ptr);

        return slice(self, off, ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off);
    }

ptr == other click to toggle source
@param [Pointer] other
Check equality between +self+ and +other+. Equality is tested on {#address}.

    static VALUE
    ptr_equals(VALUE self, VALUE other)
    {
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);

        if (NIL_P(other)) {
            return ptr->memory.address == NULL ? Qtrue : Qfalse;
        }

        return ptr->memory.address == POINTER(other)->address ? Qtrue : Qfalse;
    }

address click to toggle source
@return [Numeric] pointer's base address
Return +self+'s base address (alias: #to_i).

    static VALUE
    ptr_address(VALUE self)
    {
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);

        return ULL2NUM((uintptr_t) ptr->memory.address);
    }

Also aliased as: to_i
autorelease = autorelease click to toggle source
@param [Boolean] autorelease
@return [Boolean] +autorelease+
Set +autorelease+ attribute. See also Autorelease section.

    static VALUE
    ptr_autorelease(VALUE self, VALUE autorelease)
    {
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);
        ptr->autorelease = autorelease == Qtrue;

        return autorelease;
    }

autorelease? click to toggle source
@return [Boolean]
Get +autorelease+ attribute. See also Autorelease section.

    static VALUE
    ptr_autorelease_p(VALUE self)
    {
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);

        return ptr->autorelease ? Qtrue : Qfalse;
    }

free click to toggle source
@return [self]
Free memory pointed by +self+.

    static VALUE
    ptr_free(VALUE self)
    {
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);

        if (ptr->allocated) {
            if (ptr->storage != NULL) {
                xfree(ptr->storage);
                ptr->storage = NULL;
            }
            ptr->allocated = false;

        } else {
            VALUE caller = rb_funcall(rb_funcall(Qnil, rb_intern("caller"), 0), rb_intern("first"), 0);

            rb_warn("calling free on non allocated pointer %s from %s", RSTRING_PTR(ptr_inspect(self)), RSTRING_PTR(rb_str_to_str(caller)));
        }

        return self;
    }

initialize_copy(other) click to toggle source
@param [Pointer] other source for cloning or dupping
@return [self]
@raise {RuntimeError} if +other+ is an unbounded memory area, or is unreable/unwritable
@raise {NoMemError} if failed to allocate memory for new object
DO NOT CALL THIS METHOD.

This method is internally used by dup and clone. Memory contents is copied from `other`.

    static VALUE
    ptr_initialize_copy(VALUE self, VALUE other)
    {
        AbstractMemory* src;
        Pointer* dst;

        Data_Get_Struct(self, Pointer, dst);
        src = POINTER(other);
        if (src->size == LONG_MAX) {
            rb_raise(rb_eRuntimeError, "cannot duplicate unbounded memory area");
            return Qnil;
        }

        if ((dst->memory.flags & (MEM_RD | MEM_WR)) != (MEM_RD | MEM_WR)) {
            rb_raise(rb_eRuntimeError, "cannot duplicate unreadable/unwritable memory area");
            return Qnil;
        }

        if (dst->storage != NULL) {
            xfree(dst->storage);
            dst->storage = NULL;
        }

        dst->storage = xmalloc(src->size + 7);
        if (dst->storage == NULL) {
            rb_raise(rb_eNoMemError, "failed to allocate memory size=%lu bytes", src->size);
            return Qnil;
        }

        dst->allocated = true;
        dst->autorelease = true;
        dst->memory.address = (void *) (((uintptr_t) dst->storage + 0x7) & (uintptr_t) ~0x7UL);
        dst->memory.size = src->size;
        dst->memory.typeSize = src->typeSize;

        /* finally, copy the actual memory contents */
        memcpy(dst->memory.address, src->address, src->size);

        return self;
    }

inspect click to toggle source
@return [String]
Inspect pointer object.

    static VALUE
    ptr_inspect(VALUE self)
    {
        char buf[100];
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);

        if (ptr->memory.size != LONG_MAX) {
            snprintf(buf, sizeof(buf), "#<%s address=%p size=%lu>",
                    rb_obj_classname(self), ptr->memory.address, ptr->memory.size);
        } else {
            snprintf(buf, sizeof(buf), "#<%s address=%p>", rb_obj_classname(self), ptr->memory.address);
        }

        return rb_str_new2(buf);
    }

null? click to toggle source
@return [Boolean]
Return +true+ if +self+ is a {NULL} pointer.

    static VALUE
    ptr_null_p(VALUE self)
    {
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);

        return ptr->memory.address == NULL ? Qtrue : Qfalse;
    }

order(p1) click to toggle source

Get or set `self`'s endianness @overload order

    @return [:big, :little] endianness of +self+

@overload order(order)

    @param  [Symbol] order endianness to set (+:little+, +:big+ or +:network+). +:big+ and +:network+
     are synonymous.
    @return [self]

    static VALUE
    ptr_order(int argc, VALUE* argv, VALUE self)
    {
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);
        if (argc == 0) {
            int order = (ptr->memory.flags & MEM_SWAP) == 0 ? BYTE_ORDER : SWAPPED_ORDER;
            return order == BIG_ENDIAN ? ID2SYM(rb_intern("big")) : ID2SYM(rb_intern("little"));
        } else {
            VALUE rbOrder = Qnil;
            int order = BYTE_ORDER;

            if (rb_scan_args(argc, argv, "1", &rbOrder) < 1) {
                rb_raise(rb_eArgError, "need byte order");
            }
            if (SYMBOL_P(rbOrder)) {
                ID id = SYM2ID(rbOrder);
                if (id == rb_intern("little")) {
                    order = LITTLE_ENDIAN;

                } else if (id == rb_intern("big") || id == rb_intern("network")) {
                    order = BIG_ENDIAN;
                }
            }
            if (order != BYTE_ORDER) {
                Pointer* p2;
                VALUE retval = slice(self, 0, ptr->memory.size);

                Data_Get_Struct(retval, Pointer, p2);
                p2->memory.flags |= MEM_SWAP;
                return retval;
            }

            return self;
        }
    }

read_array_of_type(type, reader, length) click to toggle source

@param [Type] type type of data to read from pointer's contents @param [Symbol] reader method to send to `self` to read `type` @param [Numeric] length @return [Array] Read an array of `type` of length `length`. @example

    ptr.read_array_of_type(TYPE_UINT8, :get_uint8, 4) # -> [1, 2, 3, 4]

    # File lib/ffi/pointer.rb, line 94
    def read_array_of_type(type, reader, length)
      ary = []
      size = FFI.type_size(type)
      tmp = self
      length.times { |j|
        ary << tmp.send(reader)
        tmp += size unless j == length-1 # avoid OOB
      }
      ary
    end

read_string(len=nil) click to toggle source

@param [nil,Numeric] len length of string to return @return [String] Read pointer's contents as a string, or the first `len` bytes of the equivalent string if `len` is not `nil`.

    # File lib/ffi/pointer.rb, line 38
    def read_string(len=nil)
      if len
        get_bytes(0, len)
      else
        get_string(0)
      end
    end

read_string_length(len) click to toggle source

@param [Numeric] len length of string to return @return [String] Read the first `len` bytes of pointer's contents as a string.

Same as:

    ptr.read_string(len)  # with len not nil

    # File lib/ffi/pointer.rb, line 52
    def read_string_length(len)
      get_bytes(0, len)
    end

read_string_to_null() click to toggle source

@return [String] Read pointer's contents as a string.

Same as:

    ptr.read_string  # with no len

    # File lib/ffi/pointer.rb, line 61
    def read_string_to_null
      get_string(0)
    end

slice(offset, length) click to toggle source
@param [Numeric] offset
@param [Numeric] length
@return [Pointer]
Return a new {Pointer} from an existing one. This pointer points on same contents
from +offset+ for a length +length+.

    static VALUE
    ptr_slice(VALUE self, VALUE rbOffset, VALUE rbLength)
    {
        return slice(self, NUM2LONG(rbOffset), NUM2LONG(rbLength));
    }

to_i() click to toggle source
Alias for: address
inspect click to toggle source
@return [String]
Inspect pointer object.

    static VALUE
    ptr_inspect(VALUE self)
    {
        char buf[100];
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);

        if (ptr->memory.size != LONG_MAX) {
            snprintf(buf, sizeof(buf), "#<%s address=%p size=%lu>",
                    rb_obj_classname(self), ptr->memory.address, ptr->memory.size);
        } else {
            snprintf(buf, sizeof(buf), "#<%s address=%p>", rb_obj_classname(self), ptr->memory.address);
        }

        return rb_str_new2(buf);
    }

type_size() click to toggle source

    static VALUE
    ptr_type_size(VALUE self)
    {
        Pointer* ptr;

        Data_Get_Struct(self, Pointer, ptr);

        return INT2NUM(ptr->memory.typeSize);
    }

write_array_of_type(type, writer, ary) click to toggle source

@param [Type] type type of data to write to pointer's contents @param [Symbol] writer method to send to `self` to write `type` @param [Array] ary @return [self] Write `ary` in pointer's contents as `type`. @example

    ptr.write_array_of_type(TYPE_UINT8, :put_uint8, [1, 2, 3 ,4])

    # File lib/ffi/pointer.rb, line 112
    def write_array_of_type(type, writer, ary)
      size = FFI.type_size(type)
      tmp = self
      ary.each_with_index {|i, j|
        tmp.send(writer, i)
        tmp += size unless j == ary.length-1 # avoid OOB
      }
      self
    end

write_string(str, len=nil) click to toggle source

@param [String] str string to write @param [Numeric] len length of string to return @return [self] Write `str` in pointer's contents, or first `len` bytes if `len` is not `nil`.

    # File lib/ffi/pointer.rb, line 81
    def write_string(str, len=nil)
      len = str.bytesize unless len
      # Write the string data without NUL termination
      put_bytes(0, str, 0, len)
    end

write_string_length(str, len) click to toggle source

@param [String] str string to write @param [Numeric] len length of string to return @return [self] Write `len` first bytes of `str` in pointer's contents.

Same as:

    ptr.write_string(str, len)   # with len not nil

    # File lib/ffi/pointer.rb, line 72
    def write_string_length(str, len)
      put_bytes(0, str, 0, len)
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.