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