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