Class: FFI::Pointer
Relationships & Source Files | |
Extension / Inclusion / Inheritance Descendants | |
Subclasses:
|
|
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
AbstractMemory
|
|
Instance Chain:
self,
AbstractMemory
|
|
Inherits: |
FFI::AbstractMemory
|
Defined in: | ext/ffi_c/Pointer.c, lib/ffi/pointer.rb |
Overview
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
By default a pointer object frees its content when it’s garbage collected. Therefore it’s usually not necessary to call #free explicit. This behaviour may be changed with #autorelease= method. If it’s set to false
, the memory isn’t freed by the garbage collector, but stays valid until free() is called on C level or when the process terminates.
Constant Summary
-
NULL =
NULL
pointerrbffi_NullPointerSingleton
-
SIZE =
Pointer
sizePlatform::ADDRESS_SIZE / 8
AbstractMemory
- Inherited
Class Method Summary
-
.new(address) ⇒ self
constructor
A new instance of
Pointer
. -
.size ⇒ Integer
Return the size of a pointer on the current platform, in bytes.
Instance Attribute Summary
- #autorelease=(autorelease) rw
- #autorelease? ⇒ Boolean rw
- #null? ⇒ Boolean readonly
AbstractMemory
- Inherited
#size_limit? | Return |
Instance Method Summary
- #+(offset)
- #==(other)
-
#address
Alias for #to_i.
- #free
-
#initialize_copy(other)
This method is internally used by
#dup
and#clone
. -
#inspect
Alias for #to_s.
-
#order ⇒ :big, :little
Get or set
self
‘s endianness. -
#read(type) ⇒ Object
Read pointer’s contents as
type
-
#read_array_of_type(type, reader, length) ⇒ Array
Read an array of
type
of lengthlength
. -
#read_string(len = nil) ⇒ String
Read pointer’s contents as a string, or the first
len
bytes of the equivalent string iflen
is notnil
. -
#read_string_length(len) ⇒ String
Read the first
len
bytes of pointer’s contents as a string. -
#read_string_to_null ⇒ String
Read pointer’s contents as a string.
- #slice(offset, length)
- #address (also: #address)
- #to_ptr ⇒ self
- #inspect (also: #inspect)
- #type_size
-
#write(type, value) ⇒ nil
Write
value
of typetype
to pointer’s content. -
#write_array_of_type(type, writer, ary) ⇒ self
Write
ary
in pointer’s contents astype
. -
#write_string(str, len = nil) ⇒ self
Write
str
in pointer’s contents, or firstlen
bytes iflen
is notnil
. -
#write_string_length(str, len) ⇒ self
Write
len
first bytes ofstr
in pointer’s contents.
AbstractMemory
- Inherited
Constructor Details
.new(address) ⇒ self
.new(type, address) ⇒ self
self
.new(type, address) ⇒ self
A new instance of Pointer
.
# File 'ext/ffi_c/Pointer.c', line 106
static VALUE ptr_initialize(int argc, VALUE* argv, VALUE self) { Pointer* p; VALUE rbType = Qnil, rbAddress = Qnil; int typeSize = 1; TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, 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) NUM2ULL(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; RB_OBJ_WRITE(self, &p->rbParent, rbAddress); TypedData_Get_Struct(rbAddress, Pointer, &rbffi_pointer_data_type, 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; }
Class Method Details
.size ⇒ Integer
Return the size of a pointer on the current platform, in bytes
# File 'lib/ffi/pointer.rb', line 49
def self.size SIZE end
Instance Attribute Details
#autorelease=(autorelease) (rw)
Set({autorelease} attribute. See also Autorelease section.)
# File 'ext/ffi_c/Pointer.c', line 439
static VALUE ptr_autorelease(VALUE self, VALUE autorelease) { Pointer* ptr; rb_check_frozen(self); TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr); ptr->autorelease = RB_TEST(autorelease); return autorelease; }
#autorelease? ⇒ Boolean
(rw)
Get({autorelease} attribute. See also Autorelease section.)
Boolean
(rw)
Get({autorelease} attribute. See also Autorelease section.)
# File 'ext/ffi_c/Pointer.c', line 456
static VALUE ptr_autorelease_p(VALUE self) { Pointer* ptr; TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr); return ptr->autorelease ? Qtrue : Qfalse; }
#null? ⇒ Boolean
(readonly)
Return({true} if {self} is a {NULL} pointer.)
Boolean
(readonly)
Return({true} if {self} is a {NULL} pointer.)
# File 'ext/ffi_c/Pointer.c', line 288
static VALUE ptr_null_p(VALUE self) { Pointer* ptr; TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr); return ptr->memory.address == NULL ? Qtrue : Qfalse; }
Instance Method Details
#+(offset)
#a(new)
# File 'ext/ffi_c/Pointer.c', line 234
static VALUE ptr_plus(VALUE self, VALUE offset) { AbstractMemory* ptr; long off = NUM2LONG(offset); TypedData_Get_Struct(self, AbstractMemory, &rbffi_abstract_memory_data_type, ptr); return slice(self, off, ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off); }
#==(other)
#equality(between)
# File 'ext/ffi_c/Pointer.c', line 304
static VALUE ptr_equals(VALUE self, VALUE other) { Pointer* ptr; TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr); if (NIL_P(other)) { return ptr->memory.address == NULL ? Qtrue : Qfalse; } if (!rb_obj_is_kind_of(other, rbffi_PointerClass)) { return Qfalse; } else { return ptr->memory.address == POINTER(other)->address ? Qtrue : Qfalse; } }
#address
Return(+self+'s base address (alias: #to_i).)
Alias for #to_i.
#free
#memory(pointed)
# File 'ext/ffi_c/Pointer.c', line 399
static VALUE ptr_free(VALUE self) { Pointer* ptr; rb_check_frozen(self); TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, 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)
NOT(CALL)
This method is internally used by #dup
and #clone
. Memory content is copied from other
.
# File 'ext/ffi_c/Pointer.c', line 165
static VALUE ptr_initialize_copy(VALUE self, VALUE other) { AbstractMemory* src; Pointer* dst; TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, 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) ~0x7ULL); 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
#pointer(object)
Alias for #to_s.
#order ⇒ :big
, :little
#order(order) ⇒ Object
:big
, :little
#order(order) ⇒ Object
Get or set self
‘s endianness
# File 'ext/ffi_c/Pointer.c', line 353
static VALUE ptr_order(int argc, VALUE* argv, VALUE self) { Pointer* ptr; TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, 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; } else { rb_raise(rb_eArgError, "unknown byte order"); } } if (order != BYTE_ORDER) { Pointer* p2; VALUE retval = slice(self, 0, ptr->memory.size); TypedData_Get_Struct(retval, Pointer, &rbffi_pointer_data_type, p2); p2->memory.flags |= MEM_SWAP; return retval; } return self; } }
#read(type) ⇒ Object
Read pointer’s contents as type
Same as:
ptr.get(type, 0)
# File 'lib/ffi/pointer.rb', line 152
def read(type) get(type, 0) end
#read_array_of_type(type, reader, length) ⇒ Array
Read an array of type
of length length
.
#read_string(len = nil) ⇒ 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 57
def read_string(len=nil) if len return ''.b if len == 0 get_bytes(0, len) else get_string(0) end end
#read_string_length(len) ⇒ 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 72
def read_string_length(len) get_bytes(0, len) end
#read_string_to_null ⇒ String
# File 'lib/ffi/pointer.rb', line 81
def read_string_to_null get_string(0) end
#slice(offset, length)
#a(new)
#from({offset} for a length {length}.)
# File 'ext/ffi_c/Pointer.c', line 253
static VALUE ptr_slice(VALUE self, VALUE rbOffset, VALUE rbLength) { return slice(self, NUM2LONG(rbOffset), NUM2LONG(rbLength)); }
#address
Return(+self+'s base address (alias: #to_i).)
Also known as: #address
# File 'ext/ffi_c/Pointer.c', line 328
static VALUE ptr_address(VALUE self) { Pointer* ptr; TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr); return ULL2NUM((uintptr_t) ptr->memory.address); }
#to_ptr ⇒ self
# File 'lib/ffi/pointer.rb', line 142
def to_ptr self end
#inspect
#pointer(object)
Also known as: #inspect
# File 'ext/ffi_c/Pointer.c', line 264
static VALUE ptr_inspect(VALUE self) { char buf[100]; Pointer* ptr; TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, 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
[ GitHub ]# File 'ext/ffi_c/Pointer.c', line 423
static VALUE ptr_type_size(VALUE self) { Pointer* ptr; TypedData_Get_Struct(self, Pointer, &rbffi_pointer_data_type, ptr); return INT2NUM(ptr->memory.typeSize); }
#write(type, value) ⇒ nil
Write value
of type type
to pointer’s content
Same as:
ptr.put(type, 0)
# File 'lib/ffi/pointer.rb', line 163
def write(type, value) put(type, 0, value) end
#write_array_of_type(type, writer, ary) ⇒ self
Write ary
in pointer’s contents as type
.
#write_string(str, len = nil) ⇒ self
Write str
in pointer’s contents, or first len
bytes if len
is not nil
.
# File 'lib/ffi/pointer.rb', line 101
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) ⇒ 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 92
def write_string_length(str, len) put_bytes(0, str, 0, len) end