Ruby 1.9.3p327(2012-11-10revision37606)
|
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 VALUE 00021 rb_dl_dlopen(int argc, VALUE argv[], VALUE self) 00022 { 00023 return rb_class_new_instance(argc, argv, rb_cDLHandle); 00024 } 00025 00026 /* 00027 * call-seq: DL.malloc 00028 * 00029 * Allocate +size+ bytes of memory and return the integer memory address 00030 * for the allocated memory. 00031 */ 00032 VALUE 00033 rb_dl_malloc(VALUE self, VALUE size) 00034 { 00035 void *ptr; 00036 00037 rb_secure(4); 00038 ptr = (void*)ruby_xmalloc(NUM2INT(size)); 00039 return PTR2NUM(ptr); 00040 } 00041 00042 /* 00043 * call-seq: DL.realloc(addr, size) 00044 * 00045 * Change the size of the memory allocated at the memory location +addr+ to 00046 * +size+ bytes. Returns the memory address of the reallocated memory, which 00047 * may be different than the address passed in. 00048 */ 00049 VALUE 00050 rb_dl_realloc(VALUE self, VALUE addr, VALUE size) 00051 { 00052 void *ptr = NUM2PTR(addr); 00053 00054 rb_secure(4); 00055 ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size)); 00056 return PTR2NUM(ptr); 00057 } 00058 00059 /* 00060 * call-seq: DL.free(addr) 00061 * 00062 * Free the memory at address +addr+ 00063 */ 00064 VALUE 00065 rb_dl_free(VALUE self, VALUE addr) 00066 { 00067 void *ptr = NUM2PTR(addr); 00068 00069 rb_secure(4); 00070 ruby_xfree(ptr); 00071 return Qnil; 00072 } 00073 00074 VALUE 00075 rb_dl_ptr2value(VALUE self, VALUE addr) 00076 { 00077 rb_secure(4); 00078 return (VALUE)NUM2PTR(addr); 00079 } 00080 00081 VALUE 00082 rb_dl_value2ptr(VALUE self, VALUE val) 00083 { 00084 return PTR2NUM((void*)val); 00085 } 00086 00087 static void 00088 rb_dl_init_callbacks(VALUE dl) 00089 { 00090 static const char cb[] = "dl/callback.so"; 00091 00092 rb_autoload(dl, rb_intern_const("CdeclCallbackAddrs"), cb); 00093 rb_autoload(dl, rb_intern_const("CdeclCallbackProcs"), cb); 00094 #ifdef FUNC_STDCALL 00095 rb_autoload(dl, rb_intern_const("StdcallCallbackAddrs"), cb); 00096 rb_autoload(dl, rb_intern_const("StdcallCallbackProcs"), cb); 00097 #endif 00098 } 00099 00100 void 00101 Init_dl(void) 00102 { 00103 void Init_dlhandle(void); 00104 void Init_dlcfunc(void); 00105 void Init_dlptr(void); 00106 00107 rbdl_id_cdecl = rb_intern_const("cdecl"); 00108 rbdl_id_stdcall = rb_intern_const("stdcall"); 00109 00110 /* Document-module: DL 00111 * 00112 * A bridge to the dlopen() or dynamic library linker function. 00113 * 00114 * == Example 00115 * 00116 * bash $> cat > sum.c <<EOF 00117 * double sum(double *arry, int len) 00118 * { 00119 * double ret = 0; 00120 * int i; 00121 * for(i = 0; i < len; i++){ 00122 * ret = ret + arry[i]; 00123 * } 00124 * return ret; 00125 * } 00126 * 00127 * double split(double num) 00128 * { 00129 * double ret = 0; 00130 * ret = num / 2; 00131 * return ret; 00132 * } 00133 * EOF 00134 * bash $> gcc -o libsum.so -shared sum.c 00135 * bash $> cat > sum.rb <<EOF 00136 * require 'dl' 00137 * require 'dl/import' 00138 * 00139 * module LibSum 00140 * extend DL::Importer 00141 * dlload './libsum.so' 00142 * extern 'double sum(double*, int)' 00143 * extern 'double split(double)' 00144 * end 00145 * 00146 * a = [2.0, 3.0, 4.0] 00147 * 00148 * sum = LibSum.sum(a.pack("d*"), a.count) 00149 * p LibSum.split(sum) 00150 * EOF 00151 * bash $> ruby sum.rb 00152 * 4.5 00153 * 00154 * WIN! :-) 00155 */ 00156 rb_mDL = rb_define_module("DL"); 00157 00158 /* 00159 * Document-class: DL::DLError 00160 * 00161 * standard dynamic load exception 00162 */ 00163 rb_eDLError = rb_define_class_under(rb_mDL, "DLError", rb_eStandardError); 00164 00165 /* 00166 * Document-class: DL::DLTypeError 00167 * 00168 * dynamic load incorrect type exception 00169 */ 00170 rb_eDLTypeError = rb_define_class_under(rb_mDL, "DLTypeError", rb_eDLError); 00171 00172 /* Document-const: MAX_CALLBACK 00173 * 00174 * Maximum number of callbacks 00175 */ 00176 rb_define_const(rb_mDL, "MAX_CALLBACK", INT2NUM(MAX_CALLBACK)); 00177 00178 /* Document-const: DLSTACK_SIZE 00179 * 00180 * Dynamic linker stack size 00181 */ 00182 rb_define_const(rb_mDL, "DLSTACK_SIZE", INT2NUM(DLSTACK_SIZE)); 00183 00184 rb_dl_init_callbacks(rb_mDL); 00185 00186 /* Document-const: RTLD_GLOBAL 00187 * 00188 * rtld DL::Handle flag. 00189 * 00190 * The symbols defined by this library will be made available for symbol 00191 * resolution of subsequently loaded libraries. 00192 */ 00193 rb_define_const(rb_mDL, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL)); 00194 00195 /* Document-const: RTLD_LAZY 00196 * 00197 * rtld DL::Handle flag. 00198 * 00199 * Perform lazy binding. Only resolve symbols as the code that references 00200 * them is executed. If the symbol is never referenced, then it is never 00201 * resolved. (Lazy binding is only performed for function references; 00202 * references to variables are always immediately bound when the library 00203 * is loaded.) 00204 */ 00205 rb_define_const(rb_mDL, "RTLD_LAZY", INT2NUM(RTLD_LAZY)); 00206 00207 /* Document-const: RTLD_NOW 00208 * 00209 * rtld DL::Handle flag. 00210 * 00211 * If this value is specified or the environment variable LD_BIND_NOW is 00212 * set to a nonempty string, all undefined symbols in the library are 00213 * resolved before dlopen() returns. If this cannot be done an error is 00214 * returned. 00215 */ 00216 rb_define_const(rb_mDL, "RTLD_NOW", INT2NUM(RTLD_NOW)); 00217 00218 /* Document-const: TYPE_VOID 00219 * 00220 * DL::CFunc type - void 00221 */ 00222 rb_define_const(rb_mDL, "TYPE_VOID", INT2NUM(DLTYPE_VOID)); 00223 00224 /* Document-const: TYPE_VOIDP 00225 * 00226 * DL::CFunc type - void* 00227 */ 00228 rb_define_const(rb_mDL, "TYPE_VOIDP", INT2NUM(DLTYPE_VOIDP)); 00229 00230 /* Document-const: TYPE_CHAR 00231 * 00232 * DL::CFunc type - char 00233 */ 00234 rb_define_const(rb_mDL, "TYPE_CHAR", INT2NUM(DLTYPE_CHAR)); 00235 00236 /* Document-const: TYPE_SHORT 00237 * 00238 * DL::CFunc type - short 00239 */ 00240 rb_define_const(rb_mDL, "TYPE_SHORT", INT2NUM(DLTYPE_SHORT)); 00241 00242 /* Document-const: TYPE_INT 00243 * 00244 * DL::CFunc type - int 00245 */ 00246 rb_define_const(rb_mDL, "TYPE_INT", INT2NUM(DLTYPE_INT)); 00247 00248 /* Document-const: TYPE_LONG 00249 * 00250 * DL::CFunc type - long 00251 */ 00252 rb_define_const(rb_mDL, "TYPE_LONG", INT2NUM(DLTYPE_LONG)); 00253 00254 #if HAVE_LONG_LONG 00255 /* Document-const: TYPE_LONG_LONG 00256 * 00257 * DL::CFunc type - long long 00258 */ 00259 rb_define_const(rb_mDL, "TYPE_LONG_LONG", INT2NUM(DLTYPE_LONG_LONG)); 00260 #endif 00261 00262 /* Document-const: TYPE_FLOAT 00263 * 00264 * DL::CFunc type - float 00265 */ 00266 rb_define_const(rb_mDL, "TYPE_FLOAT", INT2NUM(DLTYPE_FLOAT)); 00267 00268 /* Document-const: TYPE_DOUBLE 00269 * 00270 * DL::CFunc type - double 00271 */ 00272 rb_define_const(rb_mDL, "TYPE_DOUBLE", INT2NUM(DLTYPE_DOUBLE)); 00273 00274 /* Document-const: ALIGN_VOIDP 00275 * 00276 * The Offset of a struct void* and a void* 00277 */ 00278 rb_define_const(rb_mDL, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP)); 00279 00280 /* Document-const: ALIGN_CHAR 00281 * 00282 * The Offset of a struct char and a char 00283 */ 00284 rb_define_const(rb_mDL, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR)); 00285 00286 /* Document-const: ALIGN_SHORT 00287 * 00288 * The Offset of a struct short and a short 00289 */ 00290 rb_define_const(rb_mDL, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT)); 00291 00292 /* Document-const: ALIGN_INT 00293 * 00294 * The Offset of a struct int and a int 00295 */ 00296 rb_define_const(rb_mDL, "ALIGN_INT", INT2NUM(ALIGN_INT)); 00297 00298 /* Document-const: ALIGN_LONG 00299 * 00300 * The Offset of a struct long and a long 00301 */ 00302 rb_define_const(rb_mDL, "ALIGN_LONG", INT2NUM(ALIGN_LONG)); 00303 00304 #if HAVE_LONG_LONG 00305 /* Document-const: ALIGN_LONG_LONG 00306 * 00307 * The Offset of a struct long long and a long long 00308 */ 00309 rb_define_const(rb_mDL, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG)); 00310 #endif 00311 00312 /* Document-const: ALIGN_FLOAT 00313 * 00314 * The Offset of a struct float and a float 00315 */ 00316 rb_define_const(rb_mDL, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT)); 00317 00318 /* Document-const: ALIGN_DOUBLE 00319 * 00320 * The Offset of a struct double and a double 00321 */ 00322 rb_define_const(rb_mDL, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE)); 00323 00324 /* Document-const: SIZEOF_VOIDP 00325 * 00326 * OS Dependent - sizeof(void*) 00327 */ 00328 rb_define_const(rb_mDL, "SIZEOF_VOIDP", INT2NUM(sizeof(void*))); 00329 00330 /* Document-const: SIZEOF_CHAR 00331 * 00332 * OS Dependent - sizeof(char) 00333 */ 00334 rb_define_const(rb_mDL, "SIZEOF_CHAR", INT2NUM(sizeof(char))); 00335 00336 /* Document-const: SIZEOF_SHORT 00337 * 00338 * OS Dependent - sizeof(short) 00339 */ 00340 rb_define_const(rb_mDL, "SIZEOF_SHORT", INT2NUM(sizeof(short))); 00341 00342 /* Document-const: SIZEOF_INT 00343 * 00344 * OS Dependent - sizeof(int) 00345 */ 00346 rb_define_const(rb_mDL, "SIZEOF_INT", INT2NUM(sizeof(int))); 00347 00348 /* Document-const: SIZEOF_LONG 00349 * 00350 * OS Dependent - sizeof(long) 00351 */ 00352 rb_define_const(rb_mDL, "SIZEOF_LONG", INT2NUM(sizeof(long))); 00353 00354 #if HAVE_LONG_LONG 00355 /* Document-const: SIZEOF_LONG_LONG 00356 * 00357 * OS Dependent - sizeof(long long) 00358 */ 00359 rb_define_const(rb_mDL, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG))); 00360 #endif 00361 00362 /* Document-const: SIZEOF_FLOAT 00363 * 00364 * OS Dependent - sizeof(float) 00365 */ 00366 rb_define_const(rb_mDL, "SIZEOF_FLOAT", INT2NUM(sizeof(float))); 00367 00368 /* Document-const: SIZEOF_DOUBLE 00369 * 00370 * OS Dependent - sizeof(double) 00371 */ 00372 rb_define_const(rb_mDL, "SIZEOF_DOUBLE",INT2NUM(sizeof(double))); 00373 00374 rb_define_module_function(rb_mDL, "dlwrap", rb_dl_value2ptr, 1); 00375 rb_define_module_function(rb_mDL, "dlunwrap", rb_dl_ptr2value, 1); 00376 00377 rb_define_module_function(rb_mDL, "dlopen", rb_dl_dlopen, -1); 00378 rb_define_module_function(rb_mDL, "malloc", rb_dl_malloc, 1); 00379 rb_define_module_function(rb_mDL, "realloc", rb_dl_realloc, 2); 00380 rb_define_module_function(rb_mDL, "free", rb_dl_free, 1); 00381 00382 /* Document-const: RUBY_FREE 00383 * 00384 * Address of the ruby_xfree() function 00385 */ 00386 rb_define_const(rb_mDL, "RUBY_FREE", PTR2NUM(ruby_xfree)); 00387 00388 /* Document-const: BUILD_RUBY_PLATFORM 00389 * 00390 * Platform built against (i.e. "x86_64-linux", etc.) 00391 * 00392 * See also RUBY_PLATFORM 00393 */ 00394 rb_define_const(rb_mDL, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM)); 00395 00396 /* Document-const: BUILD_RUBY_VERSION 00397 * 00398 * Ruby Version built. (i.e. "1.9.3") 00399 * 00400 * See also RUBY_VERSION 00401 */ 00402 rb_define_const(rb_mDL, "BUILD_RUBY_VERSION", rb_str_new2(RUBY_VERSION)); 00403 00404 Init_dlhandle(); 00405 Init_dlcfunc(); 00406 Init_dlptr(); 00407 } 00408