1#include <fiddle.h> 2 3VALUE mFiddle; 4VALUE rb_eFiddleError; 5 6#ifndef TYPE_SSIZE_T 7# if SIZEOF_SIZE_T == SIZEOF_INT 8# define TYPE_SSIZE_T TYPE_INT 9# elif SIZEOF_SIZE_T == SIZEOF_LONG 10# define TYPE_SSIZE_T TYPE_LONG 11# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG 12# define TYPE_SSIZE_T TYPE_LONG_LONG 13# endif 14#endif 15#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T) 16 17#ifndef TYPE_PTRDIFF_T 18# if SIZEOF_PTRDIFF_T == SIZEOF_INT 19# define TYPE_PTRDIFF_T TYPE_INT 20# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG 21# define TYPE_PTRDIFF_T TYPE_LONG 22# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG 23# define TYPE_PTRDIFF_T TYPE_LONG_LONG 24# endif 25#endif 26 27#ifndef TYPE_INTPTR_T 28# if SIZEOF_INTPTR_T == SIZEOF_INT 29# define TYPE_INTPTR_T TYPE_INT 30# elif SIZEOF_INTPTR_T == SIZEOF_LONG 31# define TYPE_INTPTR_T TYPE_LONG 32# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG 33# define TYPE_INTPTR_T TYPE_LONG_LONG 34# endif 35#endif 36#define TYPE_UINTPTR_T (-TYPE_INTPTR_T) 37 38void Init_fiddle_pointer(void); 39 40/* 41 * call-seq: Fiddle.malloc(size) 42 * 43 * Allocate +size+ bytes of memory and return the integer memory address 44 * for the allocated memory. 45 */ 46static VALUE 47rb_fiddle_malloc(VALUE self, VALUE size) 48{ 49 void *ptr; 50 51 rb_secure(4); 52 ptr = (void*)ruby_xmalloc(NUM2INT(size)); 53 return PTR2NUM(ptr); 54} 55 56/* 57 * call-seq: Fiddle.realloc(addr, size) 58 * 59 * Change the size of the memory allocated at the memory location +addr+ to 60 * +size+ bytes. Returns the memory address of the reallocated memory, which 61 * may be different than the address passed in. 62 */ 63static VALUE 64rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size) 65{ 66 void *ptr = NUM2PTR(addr); 67 68 rb_secure(4); 69 ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size)); 70 return PTR2NUM(ptr); 71} 72 73/* 74 * call-seq: Fiddle.free(addr) 75 * 76 * Free the memory at address +addr+ 77 */ 78VALUE 79rb_fiddle_free(VALUE self, VALUE addr) 80{ 81 void *ptr = NUM2PTR(addr); 82 83 rb_secure(4); 84 ruby_xfree(ptr); 85 return Qnil; 86} 87 88/* 89 * call-seq: Fiddle.dlunwrap(addr) 90 * 91 * Returns the hexadecimal representation of a memory pointer address +addr+ 92 * 93 * Example: 94 * 95 * lib = Fiddle.dlopen('/lib64/libc-2.15.so') 96 * => #<Fiddle::Handle:0x00000001342460> 97 * 98 * lib['strcpy'].to_s(16) 99 * => "7f59de6dd240" 100 * 101 * Fiddle.dlunwrap(Fiddle.dlwrap(lib['strcpy'].to_s(16))) 102 * => "7f59de6dd240" 103 */ 104VALUE 105rb_fiddle_ptr2value(VALUE self, VALUE addr) 106{ 107 rb_secure(4); 108 return (VALUE)NUM2PTR(addr); 109} 110 111/* 112 * call-seq: Fiddle.dlwrap(val) 113 * 114 * Returns a memory pointer of a function's hexadecimal address location +val+ 115 * 116 * Example: 117 * 118 * lib = Fiddle.dlopen('/lib64/libc-2.15.so') 119 * => #<Fiddle::Handle:0x00000001342460> 120 * 121 * Fiddle.dlwrap(lib['strcpy'].to_s(16)) 122 * => 25522520 123 */ 124static VALUE 125rb_fiddle_value2ptr(VALUE self, VALUE val) 126{ 127 return PTR2NUM((void*)val); 128} 129 130void Init_fiddle_handle(void); 131 132void 133Init_fiddle(void) 134{ 135 /* 136 * Document-module: Fiddle 137 * 138 * A libffi wrapper for Ruby. 139 * 140 * == Description 141 * 142 * Fiddle is an extension to translate a foreign function interface (FFI) 143 * with ruby. 144 * 145 * It wraps {libffi}[http://sourceware.org/libffi/], a popular C library 146 * which provides a portable interface that allows code written in one 147 * language to clal code written in another language. 148 * 149 * == Example 150 * 151 * Here we will use Fiddle::Function to wrap {floor(3) from 152 * libm}[http://linux.die.net/man/3/floor] 153 * 154 * require 'fiddle' 155 * 156 * libm = Fiddle.dlopen('/lib/libm.so.6') 157 * 158 * floor = Fiddle::Function.new( 159 * libm['floor'], 160 * [Fiddle::TYPE_DOUBLE], 161 * Fiddle::TYPE_DOUBLE 162 * ) 163 * 164 * puts floor.call(3.14159) #=> 3.0 165 * 166 * 167 */ 168 mFiddle = rb_define_module("Fiddle"); 169 170 /* 171 * Document-class: Fiddle::DLError 172 * 173 * standard dynamic load exception 174 */ 175 rb_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError); 176 177 /* Document-const: TYPE_VOID 178 * 179 * C type - void 180 */ 181 rb_define_const(mFiddle, "TYPE_VOID", INT2NUM(TYPE_VOID)); 182 183 /* Document-const: TYPE_VOIDP 184 * 185 * C type - void* 186 */ 187 rb_define_const(mFiddle, "TYPE_VOIDP", INT2NUM(TYPE_VOIDP)); 188 189 /* Document-const: TYPE_CHAR 190 * 191 * C type - char 192 */ 193 rb_define_const(mFiddle, "TYPE_CHAR", INT2NUM(TYPE_CHAR)); 194 195 /* Document-const: TYPE_SHORT 196 * 197 * C type - short 198 */ 199 rb_define_const(mFiddle, "TYPE_SHORT", INT2NUM(TYPE_SHORT)); 200 201 /* Document-const: TYPE_INT 202 * 203 * C type - int 204 */ 205 rb_define_const(mFiddle, "TYPE_INT", INT2NUM(TYPE_INT)); 206 207 /* Document-const: TYPE_LONG 208 * 209 * C type - long 210 */ 211 rb_define_const(mFiddle, "TYPE_LONG", INT2NUM(TYPE_LONG)); 212 213#if HAVE_LONG_LONG 214 /* Document-const: TYPE_LONG_LONG 215 * 216 * C type - long long 217 */ 218 rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG)); 219#endif 220 221 /* Document-const: TYPE_FLOAT 222 * 223 * C type - float 224 */ 225 rb_define_const(mFiddle, "TYPE_FLOAT", INT2NUM(TYPE_FLOAT)); 226 227 /* Document-const: TYPE_DOUBLE 228 * 229 * C type - double 230 */ 231 rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE)); 232 233 /* Document-const: TYPE_SIZE_T 234 * 235 * C type - size_t 236 */ 237 rb_define_const(mFiddle, "TYPE_SIZE_T", INT2NUM(TYPE_SIZE_T)); 238 239 /* Document-const: TYPE_SSIZE_T 240 * 241 * C type - ssize_t 242 */ 243 rb_define_const(mFiddle, "TYPE_SSIZE_T", INT2NUM(TYPE_SSIZE_T)); 244 245 /* Document-const: TYPE_PTRDIFF_T 246 * 247 * C type - ptrdiff_t 248 */ 249 rb_define_const(mFiddle, "TYPE_PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T)); 250 251 /* Document-const: TYPE_INTPTR_T 252 * 253 * C type - intptr_t 254 */ 255 rb_define_const(mFiddle, "TYPE_INTPTR_T", INT2NUM(TYPE_INTPTR_T)); 256 257 /* Document-const: TYPE_UINTPTR_T 258 * 259 * C type - uintptr_t 260 */ 261 rb_define_const(mFiddle, "TYPE_UINTPTR_T", INT2NUM(TYPE_UINTPTR_T)); 262 263 /* Document-const: ALIGN_VOIDP 264 * 265 * The alignment size of a void* 266 */ 267 rb_define_const(mFiddle, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP)); 268 269 /* Document-const: ALIGN_CHAR 270 * 271 * The alignment size of a char 272 */ 273 rb_define_const(mFiddle, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR)); 274 275 /* Document-const: ALIGN_SHORT 276 * 277 * The alignment size of a short 278 */ 279 rb_define_const(mFiddle, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT)); 280 281 /* Document-const: ALIGN_INT 282 * 283 * The alignment size of an int 284 */ 285 rb_define_const(mFiddle, "ALIGN_INT", INT2NUM(ALIGN_INT)); 286 287 /* Document-const: ALIGN_LONG 288 * 289 * The alignment size of a long 290 */ 291 rb_define_const(mFiddle, "ALIGN_LONG", INT2NUM(ALIGN_LONG)); 292 293#if HAVE_LONG_LONG 294 /* Document-const: ALIGN_LONG_LONG 295 * 296 * The alignment size of a long long 297 */ 298 rb_define_const(mFiddle, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG)); 299#endif 300 301 /* Document-const: ALIGN_FLOAT 302 * 303 * The alignment size of a float 304 */ 305 rb_define_const(mFiddle, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT)); 306 307 /* Document-const: ALIGN_DOUBLE 308 * 309 * The alignment size of a double 310 */ 311 rb_define_const(mFiddle, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE)); 312 313 /* Document-const: ALIGN_SIZE_T 314 * 315 * The alignment size of a size_t 316 */ 317 rb_define_const(mFiddle, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t))); 318 319 /* Document-const: ALIGN_SSIZE_T 320 * 321 * The alignment size of a ssize_t 322 */ 323 rb_define_const(mFiddle, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */ 324 325 /* Document-const: ALIGN_PTRDIFF_T 326 * 327 * The alignment size of a ptrdiff_t 328 */ 329 rb_define_const(mFiddle, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t))); 330 331 /* Document-const: ALIGN_INTPTR_T 332 * 333 * The alignment size of a intptr_t 334 */ 335 rb_define_const(mFiddle, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t))); 336 337 /* Document-const: ALIGN_UINTPTR_T 338 * 339 * The alignment size of a uintptr_t 340 */ 341 rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t))); 342 343 /* Document-const: WINDOWS 344 * 345 * Returns a boolean regarding whether the host is WIN32 346 */ 347#if defined(_WIN32) 348 rb_define_const(mFiddle, "WINDOWS", Qtrue); 349#else 350 rb_define_const(mFiddle, "WINDOWS", Qfalse); 351#endif 352 353 /* Document-const: SIZEOF_VOIDP 354 * 355 * size of a void* 356 */ 357 rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*))); 358 359 /* Document-const: SIZEOF_CHAR 360 * 361 * size of a char 362 */ 363 rb_define_const(mFiddle, "SIZEOF_CHAR", INT2NUM(sizeof(char))); 364 365 /* Document-const: SIZEOF_SHORT 366 * 367 * size of a short 368 */ 369 rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short))); 370 371 /* Document-const: SIZEOF_INT 372 * 373 * size of an int 374 */ 375 rb_define_const(mFiddle, "SIZEOF_INT", INT2NUM(sizeof(int))); 376 377 /* Document-const: SIZEOF_LONG 378 * 379 * size of a long 380 */ 381 rb_define_const(mFiddle, "SIZEOF_LONG", INT2NUM(sizeof(long))); 382 383#if HAVE_LONG_LONG 384 /* Document-const: SIZEOF_LONG_LONG 385 * 386 * size of a long long 387 */ 388 rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG))); 389#endif 390 391 /* Document-const: SIZEOF_FLOAT 392 * 393 * size of a float 394 */ 395 rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float))); 396 397 /* Document-const: SIZEOF_DOUBLE 398 * 399 * size of a double 400 */ 401 rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double))); 402 403 /* Document-const: SIZEOF_SIZE_T 404 * 405 * size of a size_t 406 */ 407 rb_define_const(mFiddle, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t))); 408 409 /* Document-const: SIZEOF_SSIZE_T 410 * 411 * size of a ssize_t 412 */ 413 rb_define_const(mFiddle, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */ 414 415 /* Document-const: SIZEOF_PTRDIFF_T 416 * 417 * size of a ptrdiff_t 418 */ 419 rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t))); 420 421 /* Document-const: SIZEOF_INTPTR_T 422 * 423 * size of a intptr_t 424 */ 425 rb_define_const(mFiddle, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t))); 426 427 /* Document-const: SIZEOF_UINTPTR_T 428 * 429 * size of a uintptr_t 430 */ 431 rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t))); 432 433 /* Document-const: RUBY_FREE 434 * 435 * Address of the ruby_xfree() function 436 */ 437 rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree)); 438 439 /* Document-const: BUILD_RUBY_PLATFORM 440 * 441 * Platform built against (i.e. "x86_64-linux", etc.) 442 * 443 * See also RUBY_PLATFORM 444 */ 445 rb_define_const(mFiddle, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM)); 446 447 rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1); 448 rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1); 449 rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1); 450 rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2); 451 rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1); 452 453 Init_fiddle_function(); 454 Init_fiddle_closure(); 455 Init_fiddle_handle(); 456 Init_fiddle_pointer(); 457} 458/* vim: set noet sws=4 sw=4: */ 459