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