CPtr is a class to handle C pointers
Get the underlying pointer for ruby object val
and return it
as a DL::CPtr object.
static VALUE rb_dlptr_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_dlptr_new(fp, 0, NULL); } else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){ char *str = StringValuePtr(val); ptr = rb_dlptr_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_cDLCPtr)){ ptr = vptr; wrap = 0; } else{ rb_raise(rb_eDLError, "to_ptr should return a CPtr object"); } } else{ VALUE num = rb_Integer(val); if (num == val) wrap = 0; ptr = rb_dlptr_new(NUM2PTR(num), 0, NULL); } OBJ_INFECT(ptr, val); if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap; return ptr; }
Allocate size
bytes of memory and associate it with an
optional freefunc
that will be called when the pointer is
garbage collected. freefunc
must be an address pointing to a
function or an instance of DL::CFunc
static VALUE rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass) { VALUE size, sym, obj, wrap = 0; long s; freefunc_t f; switch (rb_scan_args(argc, argv, "11", &size, &sym)) { case 1: s = NUM2LONG(size); f = NULL; break; case 2: s = NUM2LONG(size); f = get_freefunc(sym, &wrap); break; default: rb_bug("rb_dlptr_s_malloc"); } obj = rb_dlptr_malloc(s,f); if (wrap) RPTR_DATA(obj)->wrap[1] = wrap; return obj; }
Create a new pointer to address
with an optional
size
and freefunc
. freefunc
will be
called when the instance is garbage collected.
static VALUE rb_dlptr_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, &dlptr_data_type, data); if (data->ptr && data->free) { /* Free previous memory. Use of inappropriate initialize may cause SEGV. */ (*(data->free))(data->ptr); } data->wrap[0] = wrap; data->wrap[1] = funcwrap; data->ptr = p; data->size = s; data->free = f; } return Qnil; }
Get the underlying pointer for ruby object val
and return it
as a DL::CPtr object.
static VALUE rb_dlptr_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_dlptr_new(fp, 0, NULL); } else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){ char *str = StringValuePtr(val); ptr = rb_dlptr_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_cDLCPtr)){ ptr = vptr; wrap = 0; } else{ rb_raise(rb_eDLError, "to_ptr should return a CPtr object"); } } else{ VALUE num = rb_Integer(val); if (num == val) wrap = 0; ptr = rb_dlptr_new(NUM2PTR(num), 0, NULL); } OBJ_INFECT(ptr, val); if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap; return ptr; }
Returns a new DL::CPtr that has been advanced
n
bytes.
static VALUE rb_dlptr_plus(VALUE self, VALUE other) { void *ptr; long num, size; ptr = rb_dlptr2cptr(self); size = RPTR_DATA(self)->size; num = NUM2LONG(other); return rb_dlptr_new((char *)ptr + num, size - num, 0); }
Returns a new DL::CPtr that has been moved back
n
bytes.
static VALUE rb_dlptr_minus(VALUE self, VALUE other) { void *ptr; long num, size; ptr = rb_dlptr2cptr(self); size = RPTR_DATA(self)->size; num = NUM2LONG(other); return rb_dlptr_new((char *)ptr - num, size + num, 0); }
Returns -1 if less than, 0 if equal to, 1 if greater than
other
. Returns nil if ptr
cannot be compared to
other
.
static VALUE rb_dlptr_cmp(VALUE self, VALUE other) { void *ptr1, *ptr2; SIGNED_VALUE diff; if(!rb_obj_is_kind_of(other, rb_cDLCPtr)) return Qnil; ptr1 = rb_dlptr2cptr(self); ptr2 = rb_dlptr2cptr(other); diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2; if (!diff) return INT2FIX(0); return diff > 0 ? INT2NUM(1) : INT2NUM(-1); }
Returns true if other
wraps the same pointer, otherwise
returns false.
VALUE rb_dlptr_eql(VALUE self, VALUE other) { void *ptr1, *ptr2; if(!rb_obj_is_kind_of(other, rb_cDLCPtr)) return Qfalse; ptr1 = rb_dlptr2cptr(self); ptr2 = rb_dlptr2cptr(other); return ptr1 == ptr2 ? Qtrue : Qfalse; }
Returns integer stored at index. If start and length are given, a string containing the bytes from start of length length will be returned.
VALUE rb_dlptr_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, &dlptr_data_type, data); if (!data->ptr) rb_raise(rb_eDLError, "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_tainted_str_new((char *)data->ptr + offset, len); break; default: rb_bug("rb_dlptr_aref()"); } return retval; }
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
.
VALUE rb_dlptr_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, &dlptr_data_type, data); if (!data->ptr) rb_raise(rb_eDLError, "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_cDLCPtr) ){ mem = rb_dlptr2cptr(arg2); } else{ mem = NUM2PTR(arg2); } memcpy((char *)data->ptr + offset, mem, len); retval = arg2; break; default: rb_bug("rb_dlptr_aset()"); } return retval; }
Returns true if other
wraps the same pointer, otherwise
returns false.
VALUE rb_dlptr_eql(VALUE self, VALUE other) { void *ptr1, *ptr2; if(!rb_obj_is_kind_of(other, rb_cDLCPtr)) return Qfalse; ptr1 = rb_dlptr2cptr(self); ptr2 = rb_dlptr2cptr(other); return ptr1 == ptr2 ? Qtrue : Qfalse; }
Get the free function for this pointer. Returns DL::CFunc or nil.
static VALUE rb_dlptr_free_get(VALUE self) { struct ptr_data *pdata; TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, pdata); return rb_dlcfunc_new(pdata->free, DLTYPE_VOID, "free<anonymous>", CFUNC_CDECL); }
Set the free function for this pointer to the DL::CFunc in function
.
static VALUE rb_dlptr_free_set(VALUE self, VALUE val) { struct ptr_data *data; TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data); data->free = get_freefunc(val, &data->wrap[1]); return Qnil; }
Returns a string formatted with an easily readable representation of the internal state of the DL::CPtr
static VALUE rb_dlptr_inspect(VALUE self) { struct ptr_data *data; TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data); return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>", rb_obj_class(self), data, data->ptr, data->size, data->free); }
Returns true if this is a null pointer.
VALUE rb_dlptr_null_p(VALUE self) { struct ptr_data *data; TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data); return data->ptr ? Qfalse : Qtrue; }
Get the size of this pointer.
static VALUE rb_dlptr_size_get(VALUE self) { return LONG2NUM(RPTR_DATA(self)->size); }
Set the size of this pointer to size
static VALUE rb_dlptr_size_set(VALUE self, VALUE size) { RPTR_DATA(self)->size = NUM2LONG(size); return size; }
Returns the integer memory location of this DL::CPtr.
static VALUE rb_dlptr_to_i(VALUE self) { struct ptr_data *data; TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data); return PTR2NUM(data->ptr); }
Returns the integer memory location of this DL::CPtr.
static VALUE rb_dlptr_to_i(VALUE self) { struct ptr_data *data; TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data); return PTR2NUM(data->ptr); }
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.
static VALUE rb_dlptr_to_s(int argc, VALUE argv[], VALUE self) { struct ptr_data *data; VALUE arg1, val; int len; TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data); switch (rb_scan_args(argc, argv, "01", &arg1)) { case 0: val = rb_tainted_str_new2((char*)(data->ptr)); break; case 1: len = NUM2INT(arg1); val = rb_tainted_str_new((char*)(data->ptr), len); break; default: rb_bug("rb_dlptr_to_s"); } return val; }
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.
static VALUE rb_dlptr_to_str(int argc, VALUE argv[], VALUE self) { struct ptr_data *data; VALUE arg1, val; int len; TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data); switch (rb_scan_args(argc, argv, "01", &arg1)) { case 0: val = rb_tainted_str_new((char*)(data->ptr),data->size); break; case 1: len = NUM2INT(arg1); val = rb_tainted_str_new((char*)(data->ptr), len); break; default: rb_bug("rb_dlptr_to_str"); } return val; }
Cast this CPtr to a ruby object.
static VALUE rb_dlptr_to_value(VALUE self) { struct ptr_data *data; TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data); return (VALUE)(data->ptr); }
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.