ext/fiddle/pointer.c

Go to the documentation of this file.
00001 /* -*- C -*-
00002  * $Id$
00003  */
00004 
00005 #include <ruby/ruby.h>
00006 #include <ruby/io.h>
00007 #include <ctype.h>
00008 #include <fiddle.h>
00009 
00010 VALUE rb_cPointer;
00011 
00012 typedef void (*freefunc_t)(void*);
00013 
00014 struct ptr_data {
00015     void *ptr;
00016     long size;
00017     freefunc_t free;
00018     VALUE wrap[2];
00019 };
00020 
00021 #define RPTR_DATA(obj) ((struct ptr_data *)(DATA_PTR(obj)))
00022 
00023 static inline freefunc_t
00024 get_freefunc(VALUE func, volatile VALUE *wrap)
00025 {
00026     VALUE addrnum;
00027     if (NIL_P(func)) {
00028         *wrap = 0;
00029         return NULL;
00030     }
00031     addrnum = rb_Integer(func);
00032     *wrap = (addrnum != func) ? func : 0;
00033     return (freefunc_t)(VALUE)NUM2PTR(addrnum);
00034 }
00035 
00036 static ID id_to_ptr;
00037 
00038 static void
00039 fiddle_ptr_mark(void *ptr)
00040 {
00041     struct ptr_data *data = ptr;
00042     if (data->wrap[0]) {
00043         rb_gc_mark(data->wrap[0]);
00044     }
00045     if (data->wrap[1]) {
00046         rb_gc_mark(data->wrap[1]);
00047     }
00048 }
00049 
00050 static void
00051 fiddle_ptr_free(void *ptr)
00052 {
00053     struct ptr_data *data = ptr;
00054     if (data->ptr) {
00055         if (data->free) {
00056             (*(data->free))(data->ptr);
00057         }
00058     }
00059     xfree(ptr);
00060 }
00061 
00062 static size_t
00063 fiddle_ptr_memsize(const void *ptr)
00064 {
00065     const struct ptr_data *data = ptr;
00066     return data ? sizeof(*data) + data->size : 0;
00067 }
00068 
00069 static const rb_data_type_t fiddle_ptr_data_type = {
00070     "fiddle/pointer",
00071     {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,},
00072 };
00073 
00074 static VALUE
00075 rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
00076 {
00077     struct ptr_data *data;
00078     VALUE val;
00079 
00080     val = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data);
00081     data->ptr = ptr;
00082     data->free = func;
00083     data->size = size;
00084     OBJ_TAINT(val);
00085 
00086     return val;
00087 }
00088 
00089 static VALUE
00090 rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func)
00091 {
00092     return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func);
00093 }
00094 
00095 static VALUE
00096 rb_fiddle_ptr_malloc(long size, freefunc_t func)
00097 {
00098     void *ptr;
00099 
00100     ptr = ruby_xmalloc((size_t)size);
00101     memset(ptr,0,(size_t)size);
00102     return rb_fiddle_ptr_new(ptr, size, func);
00103 }
00104 
00105 static void *
00106 rb_fiddle_ptr2cptr(VALUE val)
00107 {
00108     struct ptr_data *data;
00109     void *ptr;
00110 
00111     if (rb_obj_is_kind_of(val, rb_cPointer)) {
00112         TypedData_Get_Struct(val, struct ptr_data, &fiddle_ptr_data_type, data);
00113         ptr = data->ptr;
00114     }
00115     else if (val == Qnil) {
00116         ptr = NULL;
00117     }
00118     else{
00119         rb_raise(rb_eTypeError, "Fiddle::Pointer was expected");
00120     }
00121 
00122     return ptr;
00123 }
00124 
00125 static VALUE
00126 rb_fiddle_ptr_s_allocate(VALUE klass)
00127 {
00128     VALUE obj;
00129     struct ptr_data *data;
00130 
00131     obj = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data);
00132     data->ptr = 0;
00133     data->size = 0;
00134     data->free = 0;
00135 
00136     return obj;
00137 }
00138 
00139 /*
00140  * call-seq:
00141  *    Fiddle::Pointer.new(address)      => fiddle_cptr
00142  *    new(address, size)                => fiddle_cptr
00143  *    new(address, size, freefunc)      => fiddle_cptr
00144  *
00145  * Create a new pointer to +address+ with an optional +size+ and +freefunc+.
00146  *
00147  * +freefunc+ will be called when the instance is garbage collected.
00148  */
00149 static VALUE
00150 rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self)
00151 {
00152     VALUE ptr, sym, size, wrap = 0, funcwrap = 0;
00153     struct ptr_data *data;
00154     void *p = NULL;
00155     freefunc_t f = NULL;
00156     long s = 0;
00157 
00158     if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) {
00159         VALUE addrnum = rb_Integer(ptr);
00160         if (addrnum != ptr) wrap = ptr;
00161         p = NUM2PTR(addrnum);
00162     }
00163     if (argc >= 2) {
00164         s = NUM2LONG(size);
00165     }
00166     if (argc >= 3) {
00167         f = get_freefunc(sym, &funcwrap);
00168     }
00169 
00170     if (p) {
00171         TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00172         if (data->ptr && data->free) {
00173             /* Free previous memory. Use of inappropriate initialize may cause SEGV. */
00174             (*(data->free))(data->ptr);
00175         }
00176         data->wrap[0] = wrap;
00177         data->wrap[1] = funcwrap;
00178         data->ptr  = p;
00179         data->size = s;
00180         data->free = f;
00181     }
00182 
00183     return Qnil;
00184 }
00185 
00186 /*
00187  * call-seq:
00188  *
00189  *    Fiddle::Pointer.malloc(size, freefunc = nil)  => fiddle pointer instance
00190  *
00191  * Allocate +size+ bytes of memory and associate it with an optional
00192  * +freefunc+ that will be called when the pointer is garbage collected.
00193  *
00194  * +freefunc+ must be an address pointing to a function or an instance of
00195  * Fiddle::Function
00196  */
00197 static VALUE
00198 rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
00199 {
00200     VALUE size, sym, obj, wrap = 0;
00201     long s;
00202     freefunc_t f;
00203 
00204     switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
00205       case 1:
00206         s = NUM2LONG(size);
00207         f = NULL;
00208         break;
00209       case 2:
00210         s = NUM2LONG(size);
00211         f = get_freefunc(sym, &wrap);
00212         break;
00213       default:
00214         rb_bug("rb_fiddle_ptr_s_malloc");
00215     }
00216 
00217     obj = rb_fiddle_ptr_malloc(s,f);
00218     if (wrap) RPTR_DATA(obj)->wrap[1] = wrap;
00219 
00220     return obj;
00221 }
00222 
00223 /*
00224  * call-seq: to_i
00225  *
00226  * Returns the integer memory location of this pointer.
00227  */
00228 static VALUE
00229 rb_fiddle_ptr_to_i(VALUE self)
00230 {
00231     struct ptr_data *data;
00232 
00233     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00234     return PTR2NUM(data->ptr);
00235 }
00236 
00237 /*
00238  * call-seq: to_value
00239  *
00240  * Cast this pointer to a ruby object.
00241  */
00242 static VALUE
00243 rb_fiddle_ptr_to_value(VALUE self)
00244 {
00245     struct ptr_data *data;
00246     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00247     return (VALUE)(data->ptr);
00248 }
00249 
00250 /*
00251  * call-seq: ptr
00252  *
00253  * Returns a new Fiddle::Pointer instance that is a dereferenced pointer for
00254  * this pointer.
00255  *
00256  * Analogous to the star operator in C.
00257  */
00258 static VALUE
00259 rb_fiddle_ptr_ptr(VALUE self)
00260 {
00261     struct ptr_data *data;
00262 
00263     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00264     return rb_fiddle_ptr_new(*((void**)(data->ptr)),0,0);
00265 }
00266 
00267 /*
00268  * call-seq: ref
00269  *
00270  * Returns a new Fiddle::Pointer instance that is a reference pointer for this
00271  * pointer.
00272  *
00273  * Analogous to the ampersand operator in C.
00274  */
00275 static VALUE
00276 rb_fiddle_ptr_ref(VALUE self)
00277 {
00278     struct ptr_data *data;
00279 
00280     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00281     return rb_fiddle_ptr_new(&(data->ptr),0,0);
00282 }
00283 
00284 /*
00285  * call-seq: null?
00286  *
00287  * Returns +true+ if this is a null pointer.
00288  */
00289 static VALUE
00290 rb_fiddle_ptr_null_p(VALUE self)
00291 {
00292     struct ptr_data *data;
00293 
00294     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00295     return data->ptr ? Qfalse : Qtrue;
00296 }
00297 
00298 /*
00299  * call-seq: free=(function)
00300  *
00301  * Set the free function for this pointer to +function+ in the given
00302  * Fiddle::Function.
00303  */
00304 static VALUE
00305 rb_fiddle_ptr_free_set(VALUE self, VALUE val)
00306 {
00307     struct ptr_data *data;
00308 
00309     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00310     data->free = get_freefunc(val, &data->wrap[1]);
00311 
00312     return Qnil;
00313 }
00314 
00315 /*
00316  * call-seq: free => Fiddle::Function
00317  *
00318  * Get the free function for this pointer.
00319  *
00320  * Returns a new instance of Fiddle::Function.
00321  *
00322  * See Fiddle::Function.new
00323  */
00324 static VALUE
00325 rb_fiddle_ptr_free_get(VALUE self)
00326 {
00327     struct ptr_data *pdata;
00328     VALUE address;
00329     VALUE arg_types;
00330     VALUE ret_type;
00331 
00332     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
00333 
00334     if (!pdata->free)
00335         return Qnil;
00336 
00337     address = PTR2NUM(pdata->free);
00338     ret_type = INT2NUM(TYPE_VOID);
00339     arg_types = rb_ary_new();
00340     rb_ary_push(arg_types, INT2NUM(TYPE_VOIDP));
00341 
00342     return rb_fiddle_new_function(address, arg_types, ret_type);
00343 }
00344 
00345 /*
00346  * call-seq:
00347  *
00348  *    ptr.to_s        => string
00349  *    ptr.to_s(len)   => string
00350  *
00351  * Returns the pointer contents as a string.
00352  *
00353  * When called with no arguments, this method will return the contents until
00354  * the first NULL byte.
00355  *
00356  * When called with +len+, a string of +len+ bytes will be returned.
00357  *
00358  * See to_str
00359  */
00360 static VALUE
00361 rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self)
00362 {
00363     struct ptr_data *data;
00364     VALUE arg1, val;
00365     int len;
00366 
00367     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00368     switch (rb_scan_args(argc, argv, "01", &arg1)) {
00369       case 0:
00370         val = rb_tainted_str_new2((char*)(data->ptr));
00371         break;
00372       case 1:
00373         len = NUM2INT(arg1);
00374         val = rb_tainted_str_new((char*)(data->ptr), len);
00375         break;
00376       default:
00377         rb_bug("rb_fiddle_ptr_to_s");
00378     }
00379 
00380     return val;
00381 }
00382 
00383 /*
00384  * call-seq:
00385  *
00386  *    ptr.to_str        => string
00387  *    ptr.to_str(len)   => string
00388  *
00389  * Returns the pointer contents as a string.
00390  *
00391  * When called with no arguments, this method will return the contents with the
00392  * length of this pointer's +size+.
00393  *
00394  * When called with +len+, a string of +len+ bytes will be returned.
00395  *
00396  * See to_s
00397  */
00398 static VALUE
00399 rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self)
00400 {
00401     struct ptr_data *data;
00402     VALUE arg1, val;
00403     int len;
00404 
00405     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00406     switch (rb_scan_args(argc, argv, "01", &arg1)) {
00407       case 0:
00408         val = rb_tainted_str_new((char*)(data->ptr),data->size);
00409         break;
00410       case 1:
00411         len = NUM2INT(arg1);
00412         val = rb_tainted_str_new((char*)(data->ptr), len);
00413         break;
00414       default:
00415         rb_bug("rb_fiddle_ptr_to_str");
00416     }
00417 
00418     return val;
00419 }
00420 
00421 /*
00422  * call-seq: inspect
00423  *
00424  * Returns a string formatted with an easily readable representation of the
00425  * internal state of the pointer.
00426  */
00427 static VALUE
00428 rb_fiddle_ptr_inspect(VALUE self)
00429 {
00430     struct ptr_data *data;
00431 
00432     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00433     return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>",
00434                       rb_obj_class(self), data, data->ptr, data->size, data->free);
00435 }
00436 
00437 /*
00438  *  call-seq:
00439  *    ptr == other    => true or false
00440  *    ptr.eql?(other) => true or false
00441  *
00442  * Returns true if +other+ wraps the same pointer, otherwise returns
00443  * false.
00444  */
00445 static VALUE
00446 rb_fiddle_ptr_eql(VALUE self, VALUE other)
00447 {
00448     void *ptr1, *ptr2;
00449 
00450     if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qfalse;
00451 
00452     ptr1 = rb_fiddle_ptr2cptr(self);
00453     ptr2 = rb_fiddle_ptr2cptr(other);
00454 
00455     return ptr1 == ptr2 ? Qtrue : Qfalse;
00456 }
00457 
00458 /*
00459  *  call-seq:
00460  *    ptr <=> other   => -1, 0, 1, or nil
00461  *
00462  * Returns -1 if less than, 0 if equal to, 1 if greater than +other+.
00463  *
00464  * Returns nil if +ptr+ cannot be compared to +other+.
00465  */
00466 static VALUE
00467 rb_fiddle_ptr_cmp(VALUE self, VALUE other)
00468 {
00469     void *ptr1, *ptr2;
00470     SIGNED_VALUE diff;
00471 
00472     if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qnil;
00473 
00474     ptr1 = rb_fiddle_ptr2cptr(self);
00475     ptr2 = rb_fiddle_ptr2cptr(other);
00476     diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2;
00477     if (!diff) return INT2FIX(0);
00478     return diff > 0 ? INT2NUM(1) : INT2NUM(-1);
00479 }
00480 
00481 /*
00482  * call-seq:
00483  *    ptr + n   => new cptr
00484  *
00485  * Returns a new pointer instance that has been advanced +n+ bytes.
00486  */
00487 static VALUE
00488 rb_fiddle_ptr_plus(VALUE self, VALUE other)
00489 {
00490     void *ptr;
00491     long num, size;
00492 
00493     ptr = rb_fiddle_ptr2cptr(self);
00494     size = RPTR_DATA(self)->size;
00495     num = NUM2LONG(other);
00496     return rb_fiddle_ptr_new((char *)ptr + num, size - num, 0);
00497 }
00498 
00499 /*
00500  * call-seq:
00501  *    ptr - n   => new cptr
00502  *
00503  * Returns a new pointer instance that has been moved back +n+ bytes.
00504  */
00505 static VALUE
00506 rb_fiddle_ptr_minus(VALUE self, VALUE other)
00507 {
00508     void *ptr;
00509     long num, size;
00510 
00511     ptr = rb_fiddle_ptr2cptr(self);
00512     size = RPTR_DATA(self)->size;
00513     num = NUM2LONG(other);
00514     return rb_fiddle_ptr_new((char *)ptr - num, size + num, 0);
00515 }
00516 
00517 /*
00518  *  call-seq:
00519  *     ptr[index]                -> an_integer
00520  *     ptr[start, length]        -> a_string
00521  *
00522  * Returns integer stored at _index_.
00523  *
00524  * If _start_ and _length_ are given, a string containing the bytes from
00525  * _start_ of _length_ will be returned.
00526  */
00527 static VALUE
00528 rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
00529 {
00530     VALUE arg0, arg1;
00531     VALUE retval = Qnil;
00532     size_t offset, len;
00533     struct ptr_data *data;
00534 
00535     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00536     if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
00537     switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
00538       case 1:
00539         offset = NUM2ULONG(arg0);
00540         retval = INT2NUM(*((char *)data->ptr + offset));
00541         break;
00542       case 2:
00543         offset = NUM2ULONG(arg0);
00544         len    = NUM2ULONG(arg1);
00545         retval = rb_tainted_str_new((char *)data->ptr + offset, len);
00546         break;
00547       default:
00548         rb_bug("rb_fiddle_ptr_aref()");
00549     }
00550     return retval;
00551 }
00552 
00553 /*
00554  *  call-seq:
00555  *     ptr[index]         = int                    ->  int
00556  *     ptr[start, length] = string or cptr or addr ->  string or dl_cptr or addr
00557  *
00558  * Set the value at +index+ to +int+.
00559  *
00560  * Or, set the memory at +start+ until +length+ with the contents of +string+,
00561  * the memory from +dl_cptr+, or the memory pointed at by the memory address
00562  * +addr+.
00563  */
00564 static VALUE
00565 rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self)
00566 {
00567     VALUE arg0, arg1, arg2;
00568     VALUE retval = Qnil;
00569     size_t offset, len;
00570     void *mem;
00571     struct ptr_data *data;
00572 
00573     TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
00574     if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
00575     switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
00576       case 2:
00577         offset = NUM2ULONG(arg0);
00578         ((char*)data->ptr)[offset] = NUM2UINT(arg1);
00579         retval = arg1;
00580         break;
00581       case 3:
00582         offset = NUM2ULONG(arg0);
00583         len    = NUM2ULONG(arg1);
00584         if (RB_TYPE_P(arg2, T_STRING)) {
00585             mem = StringValuePtr(arg2);
00586         }
00587         else if( rb_obj_is_kind_of(arg2, rb_cPointer) ){
00588             mem = rb_fiddle_ptr2cptr(arg2);
00589         }
00590         else{
00591             mem    = NUM2PTR(arg2);
00592         }
00593         memcpy((char *)data->ptr + offset, mem, len);
00594         retval = arg2;
00595         break;
00596       default:
00597         rb_bug("rb_fiddle_ptr_aset()");
00598     }
00599     return retval;
00600 }
00601 
00602 /*
00603  * call-seq: size=(size)
00604  *
00605  * Set the size of this pointer to +size+
00606  */
00607 static VALUE
00608 rb_fiddle_ptr_size_set(VALUE self, VALUE size)
00609 {
00610     RPTR_DATA(self)->size = NUM2LONG(size);
00611     return size;
00612 }
00613 
00614 /*
00615  * call-seq: size
00616  *
00617  * Get the size of this pointer.
00618  */
00619 static VALUE
00620 rb_fiddle_ptr_size_get(VALUE self)
00621 {
00622     return LONG2NUM(RPTR_DATA(self)->size);
00623 }
00624 
00625 /*
00626  * call-seq:
00627  *    Fiddle::Pointer[val]         => cptr
00628  *    to_ptr(val)  => cptr
00629  *
00630  * Get the underlying pointer for ruby object +val+ and return it as a
00631  * Fiddle::Pointer object.
00632  */
00633 static VALUE
00634 rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
00635 {
00636     VALUE ptr, wrap = val, vptr;
00637 
00638     if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
00639         rb_io_t *fptr;
00640         FILE *fp;
00641         GetOpenFile(val, fptr);
00642         fp = rb_io_stdio_file(fptr);
00643         ptr = rb_fiddle_ptr_new(fp, 0, NULL);
00644     }
00645     else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
00646         char *str = StringValuePtr(val);
00647         ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL);
00648     }
00649     else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){
00650         if (rb_obj_is_kind_of(vptr, rb_cPointer)){
00651             ptr = vptr;
00652             wrap = 0;
00653         }
00654         else{
00655             rb_raise(rb_eFiddleError, "to_ptr should return a Fiddle::Pointer object");
00656         }
00657     }
00658     else{
00659         VALUE num = rb_Integer(val);
00660         if (num == val) wrap = 0;
00661         ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL);
00662     }
00663     OBJ_INFECT(ptr, val);
00664     if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap;
00665     return ptr;
00666 }
00667 
00668 void
00669 Init_fiddle_pointer(void)
00670 {
00671     id_to_ptr = rb_intern("to_ptr");
00672 
00673     /* Document-class: Fiddle::Pointer
00674      *
00675      * Fiddle::Pointer is a class to handle C pointers
00676      *
00677      */
00678     rb_cPointer = rb_define_class_under(mFiddle, "Pointer", rb_cObject);
00679     rb_define_alloc_func(rb_cPointer, rb_fiddle_ptr_s_allocate);
00680     rb_define_singleton_method(rb_cPointer, "malloc", rb_fiddle_ptr_s_malloc, -1);
00681     rb_define_singleton_method(rb_cPointer, "to_ptr", rb_fiddle_ptr_s_to_ptr, 1);
00682     rb_define_singleton_method(rb_cPointer, "[]", rb_fiddle_ptr_s_to_ptr, 1);
00683     rb_define_method(rb_cPointer, "initialize", rb_fiddle_ptr_initialize, -1);
00684     rb_define_method(rb_cPointer, "free=", rb_fiddle_ptr_free_set, 1);
00685     rb_define_method(rb_cPointer, "free",  rb_fiddle_ptr_free_get, 0);
00686     rb_define_method(rb_cPointer, "to_i",  rb_fiddle_ptr_to_i, 0);
00687     rb_define_method(rb_cPointer, "to_int",  rb_fiddle_ptr_to_i, 0);
00688     rb_define_method(rb_cPointer, "to_value",  rb_fiddle_ptr_to_value, 0);
00689     rb_define_method(rb_cPointer, "ptr",   rb_fiddle_ptr_ptr, 0);
00690     rb_define_method(rb_cPointer, "+@", rb_fiddle_ptr_ptr, 0);
00691     rb_define_method(rb_cPointer, "ref",   rb_fiddle_ptr_ref, 0);
00692     rb_define_method(rb_cPointer, "-@", rb_fiddle_ptr_ref, 0);
00693     rb_define_method(rb_cPointer, "null?", rb_fiddle_ptr_null_p, 0);
00694     rb_define_method(rb_cPointer, "to_s", rb_fiddle_ptr_to_s, -1);
00695     rb_define_method(rb_cPointer, "to_str", rb_fiddle_ptr_to_str, -1);
00696     rb_define_method(rb_cPointer, "inspect", rb_fiddle_ptr_inspect, 0);
00697     rb_define_method(rb_cPointer, "<=>", rb_fiddle_ptr_cmp, 1);
00698     rb_define_method(rb_cPointer, "==", rb_fiddle_ptr_eql, 1);
00699     rb_define_method(rb_cPointer, "eql?", rb_fiddle_ptr_eql, 1);
00700     rb_define_method(rb_cPointer, "+", rb_fiddle_ptr_plus, 1);
00701     rb_define_method(rb_cPointer, "-", rb_fiddle_ptr_minus, 1);
00702     rb_define_method(rb_cPointer, "[]", rb_fiddle_ptr_aref, -1);
00703     rb_define_method(rb_cPointer, "[]=", rb_fiddle_ptr_aset, -1);
00704     rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0);
00705     rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1);
00706 
00707     /*  Document-const: NULL
00708      *
00709      * A NULL pointer
00710      */
00711     rb_define_const(mFiddle, "NULL", rb_fiddle_ptr_new(0, 0, 0));
00712 }
00713 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7