Class: Fiddle::Pointer
| Relationships & Source Files | |
| Namespace Children | |
| Modules: | |
| Extension / Inclusion / Inheritance Descendants | |
| Subclasses: | |
| Super Chains via Extension / Inclusion / Inheritance | |
| Class Chain: 
          self,
          FFI::DataConverter
         | |
| Inherits: | Object | 
| Defined in: | ext/fiddle/pointer.c, ext/fiddle/lib/fiddle/ffi_backend.rb | 
Overview
Pointer is a class to handle C pointers
Class Method Summary
- 
    
      .[](value)  
      (also: .to_ptr)
    
    call-seq: 
- .from_native(value, ctx)
- .malloc(size, free = nil)
- 
    
      .new(address)  ⇒ fiddle_cptr 
    
    constructor
    Create a new pointer to addresswith an optional #size andfreefunc.
- 
    
      .read(address, len)  ⇒ String 
    
    Or read the memory at address addresswith lengthlenand return a string with that memory.
- .to_native(value, ctx)
- 
    
      .to_ptr(val)  ⇒ cptr 
      (also: .[])
    
    Alias for .[]. 
- 
    
      .write(address, str)  
    
    Write bytes in strto the location pointed to byaddress.
Instance Attribute Summary
- #ffi_ptr readonly
- 
    
      #free  ⇒ Fiddle::Function 
    
    rw
    Get the free function for this pointer. 
- 
    
      #free=(function)  
    
    rw
    Set the free function for this pointer to functionin the givenFunction.
- 
    
      #freed?  ⇒ Boolean 
    
    readonly
    Returns if the free function for this pointer has been called. 
- 
    
      #null?  ⇒ Boolean 
    
    readonly
    Returns trueif this is a null pointer.
- 
    
      #size  
    
    rw
    Get the size of this pointer. 
- 
    
      #size=(size)  
    
    rw
    Set the size of this pointer to #size 
Instance Method Summary
- 
    
      #+(n)  ⇒ new cptr 
    
    Returns a new pointer instance that has been advanced nbytes.
- 
    
      #+@  
      (also: #ptr)
    
    Returns a new Pointerinstance that is a dereferenced pointer for this pointer.
- 
    
      #-(n)  ⇒ new cptr 
    
    Returns a new pointer instance that has been moved back nbytes.
- 
    
      #-@  
      (also: #ref)
    
    Returns a new Pointerinstance that is a reference pointer for this pointer.
- 
    
      #<=>(other)  ⇒ 1, ... 
    
    Returns -1 if less than, 0 if equal to, 1 if greater than other.
- 
    
      #==(other)  ⇒ Boolean 
      (also: #eql?)
    
    Returns true if otherwraps the same pointer, otherwise returns false.
- 
    
      #[](index)  ⇒ Integer 
    
    Returns integer stored at index. 
- 
    
      #[]=(index, int)  ⇒ Integer 
    
    Set the value at indextoint.
- 
    
      #call_free  ⇒ nil 
    
    Call the free function for this pointer. 
- 
    
      #eql?(other)  ⇒ Boolean 
    
    Alias for #==. 
- #initialize(addr, size = nil, free = nil) ⇒ Pointer constructor
- 
    
      #inspect  
    
    Returns a string formatted with an easily readable representation of the internal state of the pointer. 
- 
    
      #ptr  
    
    Alias for #+@. 
- 
    
      #ref  
    
    Alias for #-@. 
- 
    
      #to_i  ⇒ Integer 
      (also: #to_int)
    
    Returns the integer memory location of this pointer. 
- 
    
      #to_int  
    
    Alias for #to_i. 
- #to_ptr
- 
    
      #to_s  ⇒ String 
    
    Returns the pointer contents as a string. 
- 
    
      #to_str  ⇒ String 
    
    Returns the pointer contents as a string. 
- 
    
      #to_value  ⇒ ? 
    
    Cast this pointer to a ruby object. 
Constructor Details
    
      .new(address)  ⇒ fiddle_cptr 
      .new(address, size)  ⇒ fiddle_cptr 
      .new(address, size, freefunc)  ⇒ fiddle_cptr 
    
  
fiddle_cptr 
      .new(address, size)  ⇒ fiddle_cptr 
      .new(address, size, freefunc)  ⇒ fiddle_cptr 
    Create a new pointer to address with an optional #size and freefunc.
freefunc will be called when the instance is garbage collected.
# File 'ext/fiddle/pointer.c', line 216
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;
}
  
    #initialize(addr, size = nil, free = nil)  ⇒ Pointer 
  
# 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
Class Method Details
.[](value) Also known as: .to_ptr
# File 'ext/fiddle/pointer.c', line 772
static VALUE
rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
{
    VALUE ptr, wrap = val, vptr;
    if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
	rb_io_t *fptr;
	FILE *fp;
	GetOpenFile(val, fptr);
	fp = rb_io_stdio_file(fptr);
	ptr = rb_fiddle_ptr_new(fp, 0, NULL);
    }
    else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
	char *str = StringValuePtr(val);
        wrap = val;
	ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL);
    }
    else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){
	if (rb_obj_is_kind_of(vptr, rb_cPointer)){
	    ptr = vptr;
	    wrap = 0;
	}
	else{
	    rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object");
	}
    }
    else{
	VALUE num = rb_Integer(val);
	if (num == val) wrap = 0;
	ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL);
    }
    if (wrap) RB_OBJ_WRITE(ptr, &RPTR_DATA(ptr)->wrap[0], wrap);
    return ptr;
}
  .from_native(value, ctx)
[ GitHub ]# File 'ext/fiddle/lib/fiddle/ffi_backend.rb', line 236
def self.from_native(value, ctx) self.new(value) end
.malloc(size, free = nil)
[ GitHub ]# File 'ext/fiddle/lib/fiddle/ffi_backend.rb', line 338
def self.malloc(size, free = nil) if block_given? and free.nil? = "a free function must be supplied to #{self}.malloc " + "when it is called with a block" raise ArgumentError, end pointer = new(LibC.malloc(size), size, free) if block_given? begin yield(pointer) ensure pointer.call_free end else pointer end end
    .read(address, len)  ⇒ String   
Or read the memory at address address with length len and return a string with that memory
# File 'ext/fiddle/pointer.c', line 815
static VALUE
rb_fiddle_ptr_read_mem(VALUE klass, VALUE address, VALUE len)
{
    return rb_str_new((char *)NUM2PTR(address), NUM2ULONG(len));
}
  .to_native(value, ctx)
[ GitHub ]
    
      Fiddle::Pointer  ⇒ cptr 
      .to_ptr(val)  ⇒ cptr 
    
    Also known as: .[]
  
cptr 
      .to_ptr(val)  ⇒ cptr 
    Alias for .[].
.write(address, str)
Write bytes in str to the location pointed to by address.
# File 'ext/fiddle/pointer.c', line 827
static VALUE
rb_fiddle_ptr_write_mem(VALUE klass, VALUE addr, VALUE str)
{
    const char *ptr = StringValuePtr(str);
    memcpy(NUM2PTR(addr), ptr, RSTRING_LEN(str));
    return str;
}
  Instance Attribute Details
#ffi_ptr (readonly)
[ GitHub ]# File 'ext/fiddle/lib/fiddle/ffi_backend.rb', line 220
attr_reader :ffi_ptr
#free ⇒ Fiddle::Function (rw)
# File 'ext/fiddle/pointer.c', line 435
static VALUE
rb_fiddle_ptr_free_get(VALUE self)
{
    struct ptr_data *pdata;
    VALUE address;
    VALUE arg_types;
    VALUE ret_type;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
    if (!pdata->free)
	return Qnil;
    address = PTR2NUM(pdata->free);
    ret_type = INT2NUM(TYPE_VOID);
    arg_types = rb_ary_new();
    rb_ary_push(arg_types, INT2NUM(TYPE_VOIDP));
    return rb_fiddle_new_function(address, arg_types, ret_type);
}
  #free=(function) (rw)
Set the free function for this pointer to function in the given Function.
# File 'ext/fiddle/pointer.c', line 415
static VALUE
rb_fiddle_ptr_free_set(VALUE self, VALUE val)
{
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    data->free = get_freefunc(val, &data->wrap[1]);
    return Qnil;
}
  
    #freed?  ⇒ Boolean  (readonly)  
Returns if the free function for this pointer has been called.
# File 'ext/fiddle/pointer.c', line 476
static VALUE
rb_fiddle_ptr_freed_p(VALUE self)
{
    struct ptr_data *pdata;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
    return pdata->freed ? Qtrue : Qfalse;
}
  
    #null?  ⇒ Boolean  (readonly)  
Returns true if this is a null pointer.
# File 'ext/fiddle/pointer.c', line 400
static VALUE
rb_fiddle_ptr_null_p(VALUE self)
{
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return data->ptr ? Qfalse : Qtrue;
}
  #size (rw)
Get the size of this pointer.
# File 'ext/fiddle/pointer.c', line 758
static VALUE
rb_fiddle_ptr_size_get(VALUE self)
{
    return LONG2NUM(RPTR_DATA(self)->size);
}
  #size=(size) (rw)
Set the size of this pointer to #size
# File 'ext/fiddle/pointer.c', line 746
static VALUE
rb_fiddle_ptr_size_set(VALUE self, VALUE size)
{
    RPTR_DATA(self)->size = NUM2LONG(size);
    return size;
}
  Instance Method Details
    #+(n)  ⇒ new cptr   
Returns a new pointer instance that has been advanced n bytes.
# File 'ext/fiddle/pointer.c', line 626
static VALUE
rb_fiddle_ptr_plus(VALUE self, VALUE other)
{
    void *ptr;
    long num, size;
    ptr = rb_fiddle_ptr2cptr(self);
    size = RPTR_DATA(self)->size;
    num = NUM2LONG(other);
    return rb_fiddle_ptr_new((char *)ptr + num, size - num, 0);
}
  #+@ Also known as: #ptr
Returns a new Pointer instance that is a dereferenced pointer for this pointer.
Analogous to the star operator in C.
# File 'ext/fiddle/pointer.c', line 369
static VALUE
rb_fiddle_ptr_ptr(VALUE self)
{
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return rb_fiddle_ptr_new(*((void**)(data->ptr)),0,0);
}
  
    #-(n)  ⇒ new cptr   
Returns a new pointer instance that has been moved back n bytes.
# File 'ext/fiddle/pointer.c', line 644
static VALUE
rb_fiddle_ptr_minus(VALUE self, VALUE other)
{
    void *ptr;
    long num, size;
    ptr = rb_fiddle_ptr2cptr(self);
    size = RPTR_DATA(self)->size;
    num = NUM2LONG(other);
    return rb_fiddle_ptr_new((char *)ptr - num, size + num, 0);
}
  #-@ Also known as: #ref
Returns a new Pointer instance that is a reference pointer for this pointer.
Analogous to the ampersand operator in C.
# File 'ext/fiddle/pointer.c', line 386
static VALUE
rb_fiddle_ptr_ref(VALUE self)
{
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return rb_fiddle_ptr_new(&(data->ptr),0,0);
}
  
    #<=>(other)  ⇒ 1, ...   
Returns -1 if less than, 0 if equal to, 1 if greater than other.
Returns nil if #ptr cannot be compared to other.
# File 'ext/fiddle/pointer.c', line 605
static VALUE
rb_fiddle_ptr_cmp(VALUE self, VALUE other)
{
    void *ptr1, *ptr2;
    SIGNED_VALUE diff;
    if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qnil;
    ptr1 = rb_fiddle_ptr2cptr(self);
    ptr2 = rb_fiddle_ptr2cptr(other);
    diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2;
    if (!diff) return INT2FIX(0);
    return diff > 0 ? INT2NUM(1) : INT2NUM(-1);
}
  
    
      #==(other)  ⇒ Boolean 
      #eql?(other)  ⇒ Boolean 
    
    Also known as: #eql?
  
Boolean 
      #eql?(other)  ⇒ Boolean 
    Returns true if other wraps the same pointer, otherwise returns false.
# File 'ext/fiddle/pointer.c', line 584
static VALUE
rb_fiddle_ptr_eql(VALUE self, VALUE other)
{
    void *ptr1, *ptr2;
    if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qfalse;
    ptr1 = rb_fiddle_ptr2cptr(self);
    ptr2 = rb_fiddle_ptr2cptr(other);
    return ptr1 == ptr2 ? Qtrue : Qfalse;
}
  
    
      #[](index)  ⇒ Integer 
      #[](start, length)  ⇒ String 
    
  
Integer 
      #[](start, length)  ⇒ String 
    Returns integer stored at index.
If start and length are given, a string containing the bytes from start of length will be returned.
# File 'ext/fiddle/pointer.c', line 666
static VALUE
rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
{
    VALUE arg0, arg1;
    VALUE retval = Qnil;
    size_t offset, len;
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
    switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
      case 1:
	offset = NUM2ULONG(arg0);
	retval = INT2NUM(*((char *)data->ptr + offset));
	break;
      case 2:
	offset = NUM2ULONG(arg0);
	len    = NUM2ULONG(arg1);
	retval = rb_str_new((char *)data->ptr + offset, len);
	break;
      default:
	rb_bug("rb_fiddle_ptr_aref()");
    }
    return retval;
}
  
    
      #[]=(index, int)  ⇒ Integer 
      #[]=(start, length, string or cptr or addr)  ⇒ String, ... 
    
  
Integer 
      #[]=(start, length, string or cptr or addr)  ⇒ String, ... 
    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.
# File 'ext/fiddle/pointer.c', line 703
static VALUE
rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self)
{
    VALUE arg0, arg1, arg2;
    VALUE retval = Qnil;
    size_t offset, len;
    void *mem;
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
    switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
      case 2:
	offset = NUM2ULONG(arg0);
	((char*)data->ptr)[offset] = NUM2UINT(arg1);
	retval = arg1;
	break;
      case 3:
	offset = NUM2ULONG(arg0);
	len    = NUM2ULONG(arg1);
	if (RB_TYPE_P(arg2, T_STRING)) {
	    mem = StringValuePtr(arg2);
	}
	else if( rb_obj_is_kind_of(arg2, rb_cPointer) ){
	    mem = rb_fiddle_ptr2cptr(arg2);
	}
	else{
	    mem    = NUM2PTR(arg2);
	}
	memcpy((char *)data->ptr + offset, mem, len);
	retval = arg2;
	break;
      default:
	rb_bug("rb_fiddle_ptr_aset()");
    }
    return retval;
}
  
    #call_free  ⇒ nil   
Call the free function for this pointer. Calling more than once will do nothing. Does nothing if there is no free function attached.
# File 'ext/fiddle/pointer.c', line 462
static VALUE
rb_fiddle_ptr_call_free(VALUE self)
{
    struct ptr_data *pdata;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
    fiddle_ptr_free_ptr(pdata);
    return Qnil;
}
  
    
      #==(other)  ⇒ Boolean 
      #eql?(other)  ⇒ Boolean 
    
  
Boolean 
      #eql?(other)  ⇒ Boolean 
    Alias for #==.
# File 'ext/fiddle/pointer.c', line 871
def eql?(other) return unless other.is_a?(Pointer) self.to_i == other.to_i end
#inspect
Returns a string formatted with an easily readable representation of the internal state of the pointer.
# File 'ext/fiddle/pointer.c', line 566
static VALUE
rb_fiddle_ptr_inspect(VALUE self)
{
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>",
		      RB_OBJ_CLASSNAME(self), (void *)data, data->ptr, data->size, (void *)(VALUE)data->free);
}
  
    
      #+@  
      #ptr  
    
  
Alias for #+@.
    
      #-@  
      #ref  
    
  
Alias for #-@.
    #to_i  ⇒ Integer     Also known as: #to_int
  
Returns the integer memory location of this pointer.
# File 'ext/fiddle/pointer.c', line 339
static VALUE
rb_fiddle_ptr_to_i(VALUE self)
{
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return PTR2NUM(data->ptr);
}
  #to_int
Alias for #to_i.
#to_ptr
[ GitHub ]# File 'ext/fiddle/lib/fiddle/ffi_backend.rb', line 361
def to_ptr @ffi_ptr end
    
      #to_s  ⇒ String 
      #to_s(len)  ⇒ String 
    
  
String 
      #to_s(len)  ⇒ String 
    Returns the pointer contents as a string.
When called with no arguments, this method will return the contents until the first NULL byte.
When called with len, a string of len bytes will be returned.
See to_str
# File 'ext/fiddle/pointer.c', line 499
static VALUE
rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self)
{
    struct ptr_data *data;
    VALUE arg1, val;
    int len;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    switch (rb_scan_args(argc, argv, "01", &arg1)) {
      case 0:
	val = rb_str_new2((char*)(data->ptr));
	break;
      case 1:
	len = NUM2INT(arg1);
	val = rb_str_new((char*)(data->ptr), len);
	break;
      default:
	rb_bug("rb_fiddle_ptr_to_s");
    }
    return val;
}
  
    
      #to_str  ⇒ String 
      #to_str(len)  ⇒ String 
    
  
String 
      #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
# File 'ext/fiddle/pointer.c', line 537
static VALUE
rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self)
{
    struct ptr_data *data;
    VALUE arg1, val;
    int len;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    switch (rb_scan_args(argc, argv, "01", &arg1)) {
      case 0:
	val = rb_str_new((char*)(data->ptr),data->size);
	break;
      case 1:
	len = NUM2INT(arg1);
	val = rb_str_new((char*)(data->ptr), len);
	break;
      default:
	rb_bug("rb_fiddle_ptr_to_str");
    }
    return val;
}
  #to_value ⇒ ?
Cast this pointer to a ruby object.
# File 'ext/fiddle/pointer.c', line 353
static VALUE
rb_fiddle_ptr_to_value(VALUE self)
{
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return (VALUE)(data->ptr);
}