Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /* 00002 * ext/dl/dl.c 00003 * 00004 * doumentation: 00005 * - Vincent Batts (vbatts@hashbangbash.com) 00006 * 00007 */ 00008 #include <ruby/ruby.h> 00009 #include <ruby/io.h> 00010 #include <ctype.h> 00011 #include "dl.h" 00012 00013 VALUE rb_mDL; 00014 VALUE rb_eDLError; 00015 VALUE rb_eDLTypeError; 00016 00017 ID rbdl_id_cdecl; 00018 ID rbdl_id_stdcall; 00019 00020 #ifndef DLTYPE_SSIZE_T 00021 # if SIZEOF_SIZE_T == SIZEOF_INT 00022 # define DLTYPE_SSIZE_T DLTYPE_INT 00023 # elif SIZEOF_SIZE_T == SIZEOF_LONG 00024 # define DLTYPE_SSIZE_T DLTYPE_LONG 00025 # elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG 00026 # define DLTYPE_SSIZE_T DLTYPE_LONG_LONG 00027 # endif 00028 #endif 00029 #define DLTYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*DLTYPE_SSIZE_T) 00030 00031 #ifndef DLTYPE_PTRDIFF_T 00032 # if SIZEOF_PTRDIFF_T == SIZEOF_INT 00033 # define DLTYPE_PTRDIFF_T DLTYPE_INT 00034 # elif SIZEOF_PTRDIFF_T == SIZEOF_LONG 00035 # define DLTYPE_PTRDIFF_T DLTYPE_LONG 00036 # elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG 00037 # define DLTYPE_PTRDIFF_T DLTYPE_LONG_LONG 00038 # endif 00039 #endif 00040 00041 #ifndef DLTYPE_INTPTR_T 00042 # if SIZEOF_INTPTR_T == SIZEOF_INT 00043 # define DLTYPE_INTPTR_T DLTYPE_INT 00044 # elif SIZEOF_INTPTR_T == SIZEOF_LONG 00045 # define DLTYPE_INTPTR_T DLTYPE_LONG 00046 # elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG 00047 # define DLTYPE_INTPTR_T DLTYPE_LONG_LONG 00048 # endif 00049 #endif 00050 #define DLTYPE_UINTPTR_T (-DLTYPE_INTPTR_T) 00051 00052 /* 00053 * call-seq: DL.dlopen(so_lib) 00054 * 00055 * An interface to the dynamic linking loader 00056 * 00057 * This is a shortcut to DL::Handle.new and takes the same arguments. 00058 * 00059 * Example: 00060 * 00061 * libc_so = "/lib64/libc.so.6" 00062 * => "/lib64/libc.so.6" 00063 * 00064 * libc = DL.dlopen(libc_so) 00065 * => #<DL::Handle:0x00000000e05b00> 00066 */ 00067 VALUE 00068 rb_dl_dlopen(int argc, VALUE argv[], VALUE self) 00069 { 00070 return rb_class_new_instance(argc, argv, rb_cDLHandle); 00071 } 00072 00073 /* 00074 * call-seq: DL.malloc(size) 00075 * 00076 * Allocate +size+ bytes of memory and return the integer memory address 00077 * for the allocated memory. 00078 */ 00079 VALUE 00080 rb_dl_malloc(VALUE self, VALUE size) 00081 { 00082 void *ptr; 00083 00084 rb_secure(4); 00085 ptr = (void*)ruby_xmalloc(NUM2INT(size)); 00086 return PTR2NUM(ptr); 00087 } 00088 00089 /* 00090 * call-seq: DL.realloc(addr, size) 00091 * 00092 * Change the size of the memory allocated at the memory location +addr+ to 00093 * +size+ bytes. Returns the memory address of the reallocated memory, which 00094 * may be different than the address passed in. 00095 */ 00096 VALUE 00097 rb_dl_realloc(VALUE self, VALUE addr, VALUE size) 00098 { 00099 void *ptr = NUM2PTR(addr); 00100 00101 rb_secure(4); 00102 ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size)); 00103 return PTR2NUM(ptr); 00104 } 00105 00106 /* 00107 * call-seq: DL.free(addr) 00108 * 00109 * Free the memory at address +addr+ 00110 */ 00111 VALUE 00112 rb_dl_free(VALUE self, VALUE addr) 00113 { 00114 void *ptr = NUM2PTR(addr); 00115 00116 rb_secure(4); 00117 ruby_xfree(ptr); 00118 return Qnil; 00119 } 00120 00121 /* 00122 * call-seq: DL.dlunwrap(addr) 00123 * 00124 * Returns the hexadecimal representation of a memory pointer address +addr+ 00125 * 00126 * Example: 00127 * 00128 * lib = DL.dlopen('/lib64/libc-2.15.so') 00129 * => #<DL::Handle:0x00000001342460> 00130 * 00131 * lib['strcpy'].to_s(16) 00132 * => "7f59de6dd240" 00133 * 00134 * DL.dlunwrap(DL.dlwrap(lib['strcpy'].to_s(16))) 00135 * => "7f59de6dd240" 00136 */ 00137 VALUE 00138 rb_dl_ptr2value(VALUE self, VALUE addr) 00139 { 00140 rb_secure(4); 00141 return (VALUE)NUM2PTR(addr); 00142 } 00143 00144 /* 00145 * call-seq: DL.dlwrap(val) 00146 * 00147 * Returns a memory pointer of a function's hexadecimal address location +val+ 00148 * 00149 * Example: 00150 * 00151 * lib = DL.dlopen('/lib64/libc-2.15.so') 00152 * => #<DL::Handle:0x00000001342460> 00153 * 00154 * DL.dlwrap(lib['strcpy'].to_s(16)) 00155 * => 25522520 00156 */ 00157 VALUE 00158 rb_dl_value2ptr(VALUE self, VALUE val) 00159 { 00160 return PTR2NUM((void*)val); 00161 } 00162 00163 static void 00164 rb_dl_init_callbacks(VALUE dl) 00165 { 00166 static const char cb[] = "dl/callback.so"; 00167 00168 rb_autoload(dl, rb_intern_const("CdeclCallbackAddrs"), cb); 00169 rb_autoload(dl, rb_intern_const("CdeclCallbackProcs"), cb); 00170 #ifdef FUNC_STDCALL 00171 rb_autoload(dl, rb_intern_const("StdcallCallbackAddrs"), cb); 00172 rb_autoload(dl, rb_intern_const("StdcallCallbackProcs"), cb); 00173 #endif 00174 } 00175 00176 void 00177 Init_dl(void) 00178 { 00179 void Init_dlhandle(void); 00180 void Init_dlcfunc(void); 00181 void Init_dlptr(void); 00182 00183 rbdl_id_cdecl = rb_intern_const("cdecl"); 00184 rbdl_id_stdcall = rb_intern_const("stdcall"); 00185 00186 /* Document-module: DL 00187 * 00188 * A bridge to the dlopen() or dynamic library linker function. 00189 * 00190 * == Example 00191 * 00192 * bash $> cat > sum.c <<EOF 00193 * double sum(double *arry, int len) 00194 * { 00195 * double ret = 0; 00196 * int i; 00197 * for(i = 0; i < len; i++){ 00198 * ret = ret + arry[i]; 00199 * } 00200 * return ret; 00201 * } 00202 * 00203 * double split(double num) 00204 * { 00205 * double ret = 0; 00206 * ret = num / 2; 00207 * return ret; 00208 * } 00209 * EOF 00210 * bash $> gcc -o libsum.so -shared sum.c 00211 * bash $> cat > sum.rb <<EOF 00212 * require 'dl' 00213 * require 'dl/import' 00214 * 00215 * module LibSum 00216 * extend DL::Importer 00217 * dlload './libsum.so' 00218 * extern 'double sum(double*, int)' 00219 * extern 'double split(double)' 00220 * end 00221 * 00222 * a = [2.0, 3.0, 4.0] 00223 * 00224 * sum = LibSum.sum(a.pack("d*"), a.count) 00225 * p LibSum.split(sum) 00226 * EOF 00227 * bash $> ruby sum.rb 00228 * 4.5 00229 * 00230 * WIN! :-) 00231 */ 00232 rb_mDL = rb_define_module("DL"); 00233 00234 /* 00235 * Document-class: DL::DLError 00236 * 00237 * standard dynamic load exception 00238 */ 00239 rb_eDLError = rb_define_class_under(rb_mDL, "DLError", rb_eStandardError); 00240 00241 /* 00242 * Document-class: DL::DLTypeError 00243 * 00244 * dynamic load incorrect type exception 00245 */ 00246 rb_eDLTypeError = rb_define_class_under(rb_mDL, "DLTypeError", rb_eDLError); 00247 00248 /* Document-const: MAX_CALLBACK 00249 * 00250 * Maximum number of callbacks 00251 */ 00252 rb_define_const(rb_mDL, "MAX_CALLBACK", INT2NUM(MAX_CALLBACK)); 00253 00254 /* Document-const: DLSTACK_SIZE 00255 * 00256 * Dynamic linker stack size 00257 */ 00258 rb_define_const(rb_mDL, "DLSTACK_SIZE", INT2NUM(DLSTACK_SIZE)); 00259 00260 rb_dl_init_callbacks(rb_mDL); 00261 00262 /* Document-const: RTLD_GLOBAL 00263 * 00264 * rtld DL::Handle flag. 00265 * 00266 * The symbols defined by this library will be made available for symbol 00267 * resolution of subsequently loaded libraries. 00268 */ 00269 rb_define_const(rb_mDL, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL)); 00270 00271 /* Document-const: RTLD_LAZY 00272 * 00273 * rtld DL::Handle flag. 00274 * 00275 * Perform lazy binding. Only resolve symbols as the code that references 00276 * them is executed. If the symbol is never referenced, then it is never 00277 * resolved. (Lazy binding is only performed for function references; 00278 * references to variables are always immediately bound when the library 00279 * is loaded.) 00280 */ 00281 rb_define_const(rb_mDL, "RTLD_LAZY", INT2NUM(RTLD_LAZY)); 00282 00283 /* Document-const: RTLD_NOW 00284 * 00285 * rtld DL::Handle flag. 00286 * 00287 * If this value is specified or the environment variable LD_BIND_NOW is 00288 * set to a nonempty string, all undefined symbols in the library are 00289 * resolved before dlopen() returns. If this cannot be done an error is 00290 * returned. 00291 */ 00292 rb_define_const(rb_mDL, "RTLD_NOW", INT2NUM(RTLD_NOW)); 00293 00294 /* Document-const: TYPE_VOID 00295 * 00296 * DL::CFunc type - void 00297 */ 00298 rb_define_const(rb_mDL, "TYPE_VOID", INT2NUM(DLTYPE_VOID)); 00299 00300 /* Document-const: TYPE_VOIDP 00301 * 00302 * DL::CFunc type - void* 00303 */ 00304 rb_define_const(rb_mDL, "TYPE_VOIDP", INT2NUM(DLTYPE_VOIDP)); 00305 00306 /* Document-const: TYPE_CHAR 00307 * 00308 * DL::CFunc type - char 00309 */ 00310 rb_define_const(rb_mDL, "TYPE_CHAR", INT2NUM(DLTYPE_CHAR)); 00311 00312 /* Document-const: TYPE_SHORT 00313 * 00314 * DL::CFunc type - short 00315 */ 00316 rb_define_const(rb_mDL, "TYPE_SHORT", INT2NUM(DLTYPE_SHORT)); 00317 00318 /* Document-const: TYPE_INT 00319 * 00320 * DL::CFunc type - int 00321 */ 00322 rb_define_const(rb_mDL, "TYPE_INT", INT2NUM(DLTYPE_INT)); 00323 00324 /* Document-const: TYPE_LONG 00325 * 00326 * DL::CFunc type - long 00327 */ 00328 rb_define_const(rb_mDL, "TYPE_LONG", INT2NUM(DLTYPE_LONG)); 00329 00330 #if HAVE_LONG_LONG 00331 /* Document-const: TYPE_LONG_LONG 00332 * 00333 * DL::CFunc type - long long 00334 */ 00335 rb_define_const(rb_mDL, "TYPE_LONG_LONG", INT2NUM(DLTYPE_LONG_LONG)); 00336 #endif 00337 00338 /* Document-const: TYPE_FLOAT 00339 * 00340 * DL::CFunc type - float 00341 */ 00342 rb_define_const(rb_mDL, "TYPE_FLOAT", INT2NUM(DLTYPE_FLOAT)); 00343 00344 /* Document-const: TYPE_DOUBLE 00345 * 00346 * DL::CFunc type - double 00347 */ 00348 rb_define_const(rb_mDL, "TYPE_DOUBLE", INT2NUM(DLTYPE_DOUBLE)); 00349 00350 /* Document-const: TYPE_SIZE_T 00351 * 00352 * DL::CFunc type - size_t 00353 */ 00354 rb_define_const(rb_mDL, "TYPE_SIZE_T", INT2NUM(DLTYPE_SIZE_T)); 00355 00356 /* Document-const: TYPE_SSIZE_T 00357 * 00358 * DL::CFunc type - ssize_t 00359 */ 00360 rb_define_const(rb_mDL, "TYPE_SSIZE_T", INT2NUM(DLTYPE_SSIZE_T)); 00361 00362 /* Document-const: TYPE_PTRDIFF_T 00363 * 00364 * DL::CFunc type - ptrdiff_t 00365 */ 00366 rb_define_const(rb_mDL, "TYPE_PTRDIFF_T", INT2NUM(DLTYPE_PTRDIFF_T)); 00367 00368 /* Document-const: TYPE_INTPTR_T 00369 * 00370 * DL::CFunc type - intptr_t 00371 */ 00372 rb_define_const(rb_mDL, "TYPE_INTPTR_T", INT2NUM(DLTYPE_INTPTR_T)); 00373 00374 /* Document-const: TYPE_UINTPTR_T 00375 * 00376 * DL::CFunc type - uintptr_t 00377 */ 00378 rb_define_const(rb_mDL, "TYPE_UINTPTR_T", INT2NUM(DLTYPE_UINTPTR_T)); 00379 00380 /* Document-const: ALIGN_VOIDP 00381 * 00382 * The alignment size of a void* 00383 */ 00384 rb_define_const(rb_mDL, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP)); 00385 00386 /* Document-const: ALIGN_CHAR 00387 * 00388 * The alignment size of a char 00389 */ 00390 rb_define_const(rb_mDL, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR)); 00391 00392 /* Document-const: ALIGN_SHORT 00393 * 00394 * The alignment size of a short 00395 */ 00396 rb_define_const(rb_mDL, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT)); 00397 00398 /* Document-const: ALIGN_INT 00399 * 00400 * The alignment size of an int 00401 */ 00402 rb_define_const(rb_mDL, "ALIGN_INT", INT2NUM(ALIGN_INT)); 00403 00404 /* Document-const: ALIGN_LONG 00405 * 00406 * The alignment size of a long 00407 */ 00408 rb_define_const(rb_mDL, "ALIGN_LONG", INT2NUM(ALIGN_LONG)); 00409 00410 #if HAVE_LONG_LONG 00411 /* Document-const: ALIGN_LONG_LONG 00412 * 00413 * The alignment size of a long long 00414 */ 00415 rb_define_const(rb_mDL, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG)); 00416 #endif 00417 00418 /* Document-const: ALIGN_FLOAT 00419 * 00420 * The alignment size of a float 00421 */ 00422 rb_define_const(rb_mDL, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT)); 00423 00424 /* Document-const: ALIGN_DOUBLE 00425 * 00426 * The alignment size of a double 00427 */ 00428 rb_define_const(rb_mDL, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE)); 00429 00430 /* Document-const: ALIGN_SIZE_T 00431 * 00432 * The alignment size of a size_t 00433 */ 00434 rb_define_const(rb_mDL, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t))); 00435 00436 /* Document-const: ALIGN_SSIZE_T 00437 * 00438 * The alignment size of a ssize_t 00439 */ 00440 rb_define_const(rb_mDL, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */ 00441 00442 /* Document-const: ALIGN_PTRDIFF_T 00443 * 00444 * The alignment size of a ptrdiff_t 00445 */ 00446 rb_define_const(rb_mDL, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t))); 00447 00448 /* Document-const: ALIGN_INTPTR_T 00449 * 00450 * The alignment size of a intptr_t 00451 */ 00452 rb_define_const(rb_mDL, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t))); 00453 00454 /* Document-const: ALIGN_UINTPTR_T 00455 * 00456 * The alignment size of a uintptr_t 00457 */ 00458 rb_define_const(rb_mDL, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t))); 00459 00460 /* Document-const: SIZEOF_VOIDP 00461 * 00462 * size of a void* 00463 */ 00464 rb_define_const(rb_mDL, "SIZEOF_VOIDP", INT2NUM(sizeof(void*))); 00465 00466 /* Document-const: SIZEOF_CHAR 00467 * 00468 * size of a char 00469 */ 00470 rb_define_const(rb_mDL, "SIZEOF_CHAR", INT2NUM(sizeof(char))); 00471 00472 /* Document-const: SIZEOF_SHORT 00473 * 00474 * size of a short 00475 */ 00476 rb_define_const(rb_mDL, "SIZEOF_SHORT", INT2NUM(sizeof(short))); 00477 00478 /* Document-const: SIZEOF_INT 00479 * 00480 * size of an int 00481 */ 00482 rb_define_const(rb_mDL, "SIZEOF_INT", INT2NUM(sizeof(int))); 00483 00484 /* Document-const: SIZEOF_LONG 00485 * 00486 * size of a long 00487 */ 00488 rb_define_const(rb_mDL, "SIZEOF_LONG", INT2NUM(sizeof(long))); 00489 00490 #if HAVE_LONG_LONG 00491 /* Document-const: SIZEOF_LONG_LONG 00492 * 00493 * size of a long long 00494 */ 00495 rb_define_const(rb_mDL, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG))); 00496 #endif 00497 00498 /* Document-const: SIZEOF_FLOAT 00499 * 00500 * size of a float 00501 */ 00502 rb_define_const(rb_mDL, "SIZEOF_FLOAT", INT2NUM(sizeof(float))); 00503 00504 /* Document-const: SIZEOF_DOUBLE 00505 * 00506 * size of a double 00507 */ 00508 rb_define_const(rb_mDL, "SIZEOF_DOUBLE",INT2NUM(sizeof(double))); 00509 00510 /* Document-const: SIZEOF_SIZE_T 00511 * 00512 * size of a size_t 00513 */ 00514 rb_define_const(rb_mDL, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t))); 00515 00516 /* Document-const: SIZEOF_SSIZE_T 00517 * 00518 * size of a ssize_t 00519 */ 00520 rb_define_const(rb_mDL, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */ 00521 00522 /* Document-const: SIZEOF_PTRDIFF_T 00523 * 00524 * size of a ptrdiff_t 00525 */ 00526 rb_define_const(rb_mDL, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t))); 00527 00528 /* Document-const: SIZEOF_INTPTR_T 00529 * 00530 * size of a intptr_t 00531 */ 00532 rb_define_const(rb_mDL, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t))); 00533 00534 /* Document-const: SIZEOF_UINTPTR_T 00535 * 00536 * size of a uintptr_t 00537 */ 00538 rb_define_const(rb_mDL, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t))); 00539 00540 rb_define_module_function(rb_mDL, "dlwrap", rb_dl_value2ptr, 1); 00541 rb_define_module_function(rb_mDL, "dlunwrap", rb_dl_ptr2value, 1); 00542 00543 rb_define_module_function(rb_mDL, "dlopen", rb_dl_dlopen, -1); 00544 rb_define_module_function(rb_mDL, "malloc", rb_dl_malloc, 1); 00545 rb_define_module_function(rb_mDL, "realloc", rb_dl_realloc, 2); 00546 rb_define_module_function(rb_mDL, "free", rb_dl_free, 1); 00547 00548 /* Document-const: RUBY_FREE 00549 * 00550 * Address of the ruby_xfree() function 00551 */ 00552 rb_define_const(rb_mDL, "RUBY_FREE", PTR2NUM(ruby_xfree)); 00553 00554 /* Document-const: BUILD_RUBY_PLATFORM 00555 * 00556 * Platform built against (i.e. "x86_64-linux", etc.) 00557 * 00558 * See also RUBY_PLATFORM 00559 */ 00560 rb_define_const(rb_mDL, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM)); 00561 00562 /* Document-const: BUILD_RUBY_VERSION 00563 * 00564 * Ruby Version built. (i.e. "1.9.3") 00565 * 00566 * See also RUBY_VERSION 00567 */ 00568 rb_define_const(rb_mDL, "BUILD_RUBY_VERSION", rb_str_new2(RUBY_VERSION)); 00569 00570 Init_dlhandle(); 00571 Init_dlcfunc(); 00572 Init_dlptr(); 00573 } 00574