Ruby  2.0.0p247(2013-06-27revision41674)
ext/fiddle/fiddle.c
Go to the documentation of this file.
00001 #include <fiddle.h>
00002 
00003 VALUE mFiddle;
00004 VALUE rb_eFiddleError;
00005 
00006 #ifndef TYPE_SSIZE_T
00007 # if SIZEOF_SIZE_T == SIZEOF_INT
00008 #   define TYPE_SSIZE_T TYPE_INT
00009 # elif SIZEOF_SIZE_T == SIZEOF_LONG
00010 #   define TYPE_SSIZE_T TYPE_LONG
00011 # elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
00012 #   define TYPE_SSIZE_T TYPE_LONG_LONG
00013 # endif
00014 #endif
00015 #define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T)
00016 
00017 #ifndef TYPE_PTRDIFF_T
00018 # if SIZEOF_PTRDIFF_T == SIZEOF_INT
00019 #   define TYPE_PTRDIFF_T TYPE_INT
00020 # elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
00021 #   define TYPE_PTRDIFF_T TYPE_LONG
00022 # elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
00023 #   define TYPE_PTRDIFF_T TYPE_LONG_LONG
00024 # endif
00025 #endif
00026 
00027 #ifndef TYPE_INTPTR_T
00028 # if SIZEOF_INTPTR_T == SIZEOF_INT
00029 #   define TYPE_INTPTR_T TYPE_INT
00030 # elif SIZEOF_INTPTR_T == SIZEOF_LONG
00031 #   define TYPE_INTPTR_T TYPE_LONG
00032 # elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
00033 #   define TYPE_INTPTR_T TYPE_LONG_LONG
00034 # endif
00035 #endif
00036 #define TYPE_UINTPTR_T (-TYPE_INTPTR_T)
00037 
00038 void Init_fiddle_pointer(void);
00039 
00040 /*
00041  * call-seq: Fiddle.malloc(size)
00042  *
00043  * Allocate +size+ bytes of memory and return the integer memory address
00044  * for the allocated memory.
00045  */
00046 static VALUE
00047 rb_fiddle_malloc(VALUE self, VALUE size)
00048 {
00049     void *ptr;
00050 
00051     rb_secure(4);
00052     ptr = (void*)ruby_xmalloc(NUM2INT(size));
00053     return PTR2NUM(ptr);
00054 }
00055 
00056 /*
00057  * call-seq: Fiddle.realloc(addr, size)
00058  *
00059  * Change the size of the memory allocated at the memory location +addr+ to
00060  * +size+ bytes.  Returns the memory address of the reallocated memory, which
00061  * may be different than the address passed in.
00062  */
00063 static VALUE
00064 rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size)
00065 {
00066     void *ptr = NUM2PTR(addr);
00067 
00068     rb_secure(4);
00069     ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size));
00070     return PTR2NUM(ptr);
00071 }
00072 
00073 /*
00074  * call-seq: Fiddle.free(addr)
00075  *
00076  * Free the memory at address +addr+
00077  */
00078 VALUE
00079 rb_fiddle_free(VALUE self, VALUE addr)
00080 {
00081     void *ptr = NUM2PTR(addr);
00082 
00083     rb_secure(4);
00084     ruby_xfree(ptr);
00085     return Qnil;
00086 }
00087 
00088 /*
00089  * call-seq: Fiddle.dlunwrap(addr)
00090  *
00091  * Returns the hexadecimal representation of a memory pointer address +addr+
00092  *
00093  * Example:
00094  *
00095  *   lib = Fiddle.dlopen('/lib64/libc-2.15.so')
00096  *   => #<Fiddle::Handle:0x00000001342460>
00097  *
00098  *   lib['strcpy'].to_s(16)
00099  *   => "7f59de6dd240"
00100  *
00101  *   Fiddle.dlunwrap(Fiddle.dlwrap(lib['strcpy'].to_s(16)))
00102  *   => "7f59de6dd240"
00103  */
00104 VALUE
00105 rb_fiddle_ptr2value(VALUE self, VALUE addr)
00106 {
00107     rb_secure(4);
00108     return (VALUE)NUM2PTR(addr);
00109 }
00110 
00111 /*
00112  * call-seq: Fiddle.dlwrap(val)
00113  *
00114  * Returns a memory pointer of a function's hexadecimal address location +val+
00115  *
00116  * Example:
00117  *
00118  *   lib = Fiddle.dlopen('/lib64/libc-2.15.so')
00119  *   => #<Fiddle::Handle:0x00000001342460>
00120  *
00121  *   Fiddle.dlwrap(lib['strcpy'].to_s(16))
00122  *   => 25522520
00123  */
00124 static VALUE
00125 rb_fiddle_value2ptr(VALUE self, VALUE val)
00126 {
00127     return PTR2NUM((void*)val);
00128 }
00129 
00130 void Init_fiddle_handle(void);
00131 
00132 void
00133 Init_fiddle(void)
00134 {
00135     /*
00136      * Document-module: Fiddle
00137      *
00138      * A libffi wrapper for Ruby.
00139      *
00140      * == Description
00141      *
00142      * Fiddle is an extension to translate a foreign function interface (FFI)
00143      * with ruby.
00144      *
00145      * It wraps {libffi}[http://sourceware.org/libffi/], a popular C library
00146      * which provides a portable interface that allows code written in one
00147      * language to clal code written in another language.
00148      *
00149      * == Example
00150      *
00151      * Here we will use Fiddle::Function to wrap {floor(3) from
00152      * libm}[http://linux.die.net/man/3/floor]
00153      *
00154      *      require 'fiddle'
00155      *
00156      *      libm = Fiddle.dlopen('/lib/libm.so.6')
00157      *
00158      *      floor = Fiddle::Function.new(
00159      *        libm['floor'],
00160      *        [Fiddle::TYPE_DOUBLE],
00161      *        Fiddle::TYPE_DOUBLE
00162      *      )
00163      *
00164      *      puts floor.call(3.14159) #=> 3.0
00165      *
00166      *
00167      */
00168     mFiddle = rb_define_module("Fiddle");
00169 
00170     /*
00171      * Document-class: Fiddle::DLError
00172      *
00173      * standard dynamic load exception
00174      */
00175     rb_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError);
00176 
00177     /* Document-const: TYPE_VOID
00178      *
00179      * C type - void
00180      */
00181     rb_define_const(mFiddle, "TYPE_VOID",      INT2NUM(TYPE_VOID));
00182 
00183     /* Document-const: TYPE_VOIDP
00184      *
00185      * C type - void*
00186      */
00187     rb_define_const(mFiddle, "TYPE_VOIDP",     INT2NUM(TYPE_VOIDP));
00188 
00189     /* Document-const: TYPE_CHAR
00190      *
00191      * C type - char
00192      */
00193     rb_define_const(mFiddle, "TYPE_CHAR",      INT2NUM(TYPE_CHAR));
00194 
00195     /* Document-const: TYPE_SHORT
00196      *
00197      * C type - short
00198      */
00199     rb_define_const(mFiddle, "TYPE_SHORT",     INT2NUM(TYPE_SHORT));
00200 
00201     /* Document-const: TYPE_INT
00202      *
00203      * C type - int
00204      */
00205     rb_define_const(mFiddle, "TYPE_INT",       INT2NUM(TYPE_INT));
00206 
00207     /* Document-const: TYPE_LONG
00208      *
00209      * C type - long
00210      */
00211     rb_define_const(mFiddle, "TYPE_LONG",      INT2NUM(TYPE_LONG));
00212 
00213 #if HAVE_LONG_LONG
00214     /* Document-const: TYPE_LONG_LONG
00215      *
00216      * C type - long long
00217      */
00218     rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG));
00219 #endif
00220 
00221     /* Document-const: TYPE_FLOAT
00222      *
00223      * C type - float
00224      */
00225     rb_define_const(mFiddle, "TYPE_FLOAT",     INT2NUM(TYPE_FLOAT));
00226 
00227     /* Document-const: TYPE_DOUBLE
00228      *
00229      * C type - double
00230      */
00231     rb_define_const(mFiddle, "TYPE_DOUBLE",    INT2NUM(TYPE_DOUBLE));
00232 
00233     /* Document-const: TYPE_SIZE_T
00234      *
00235      * C type - size_t
00236      */
00237     rb_define_const(mFiddle, "TYPE_SIZE_T",   INT2NUM(TYPE_SIZE_T));
00238 
00239     /* Document-const: TYPE_SSIZE_T
00240      *
00241      * C type - ssize_t
00242      */
00243     rb_define_const(mFiddle, "TYPE_SSIZE_T",   INT2NUM(TYPE_SSIZE_T));
00244 
00245     /* Document-const: TYPE_PTRDIFF_T
00246      *
00247      * C type - ptrdiff_t
00248      */
00249     rb_define_const(mFiddle, "TYPE_PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T));
00250 
00251     /* Document-const: TYPE_INTPTR_T
00252      *
00253      * C type - intptr_t
00254      */
00255     rb_define_const(mFiddle, "TYPE_INTPTR_T",  INT2NUM(TYPE_INTPTR_T));
00256 
00257     /* Document-const: TYPE_UINTPTR_T
00258      *
00259      * C type - uintptr_t
00260      */
00261     rb_define_const(mFiddle, "TYPE_UINTPTR_T",  INT2NUM(TYPE_UINTPTR_T));
00262 
00263     /* Document-const: ALIGN_VOIDP
00264      *
00265      * The alignment size of a void*
00266      */
00267     rb_define_const(mFiddle, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));
00268 
00269     /* Document-const: ALIGN_CHAR
00270      *
00271      * The alignment size of a char
00272      */
00273     rb_define_const(mFiddle, "ALIGN_CHAR",  INT2NUM(ALIGN_CHAR));
00274 
00275     /* Document-const: ALIGN_SHORT
00276      *
00277      * The alignment size of a short
00278      */
00279     rb_define_const(mFiddle, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));
00280 
00281     /* Document-const: ALIGN_INT
00282      *
00283      * The alignment size of an int
00284      */
00285     rb_define_const(mFiddle, "ALIGN_INT",   INT2NUM(ALIGN_INT));
00286 
00287     /* Document-const: ALIGN_LONG
00288      *
00289      * The alignment size of a long
00290      */
00291     rb_define_const(mFiddle, "ALIGN_LONG",  INT2NUM(ALIGN_LONG));
00292 
00293 #if HAVE_LONG_LONG
00294     /* Document-const: ALIGN_LONG_LONG
00295      *
00296      * The alignment size of a long long
00297      */
00298     rb_define_const(mFiddle, "ALIGN_LONG_LONG",  INT2NUM(ALIGN_LONG_LONG));
00299 #endif
00300 
00301     /* Document-const: ALIGN_FLOAT
00302      *
00303      * The alignment size of a float
00304      */
00305     rb_define_const(mFiddle, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));
00306 
00307     /* Document-const: ALIGN_DOUBLE
00308      *
00309      * The alignment size of a double
00310      */
00311     rb_define_const(mFiddle, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));
00312 
00313     /* Document-const: ALIGN_SIZE_T
00314      *
00315      * The alignment size of a size_t
00316      */
00317     rb_define_const(mFiddle, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t)));
00318 
00319     /* Document-const: ALIGN_SSIZE_T
00320      *
00321      * The alignment size of a ssize_t
00322      */
00323     rb_define_const(mFiddle, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */
00324 
00325     /* Document-const: ALIGN_PTRDIFF_T
00326      *
00327      * The alignment size of a ptrdiff_t
00328      */
00329     rb_define_const(mFiddle, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t)));
00330 
00331     /* Document-const: ALIGN_INTPTR_T
00332      *
00333      * The alignment size of a intptr_t
00334      */
00335     rb_define_const(mFiddle, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t)));
00336 
00337     /* Document-const: ALIGN_UINTPTR_T
00338      *
00339      * The alignment size of a uintptr_t
00340      */
00341     rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t)));
00342 
00343     /* Document-const: WINDOWS
00344      *
00345      * Returns a boolean regarding whether the host is WIN32
00346      */
00347 #if defined(_WIN32)
00348     rb_define_const(mFiddle, "WINDOWS", Qtrue);
00349 #else
00350     rb_define_const(mFiddle, "WINDOWS", Qfalse);
00351 #endif
00352 
00353     /* Document-const: SIZEOF_VOIDP
00354      *
00355      * size of a void*
00356      */
00357     rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*)));
00358 
00359     /* Document-const: SIZEOF_CHAR
00360      *
00361      * size of a char
00362      */
00363     rb_define_const(mFiddle, "SIZEOF_CHAR",  INT2NUM(sizeof(char)));
00364 
00365     /* Document-const: SIZEOF_SHORT
00366      *
00367      * size of a short
00368      */
00369     rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short)));
00370 
00371     /* Document-const: SIZEOF_INT
00372      *
00373      * size of an int
00374      */
00375     rb_define_const(mFiddle, "SIZEOF_INT",   INT2NUM(sizeof(int)));
00376 
00377     /* Document-const: SIZEOF_LONG
00378      *
00379      * size of a long
00380      */
00381     rb_define_const(mFiddle, "SIZEOF_LONG",  INT2NUM(sizeof(long)));
00382 
00383 #if HAVE_LONG_LONG
00384     /* Document-const: SIZEOF_LONG_LONG
00385      *
00386      * size of a long long
00387      */
00388     rb_define_const(mFiddle, "SIZEOF_LONG_LONG",  INT2NUM(sizeof(LONG_LONG)));
00389 #endif
00390 
00391     /* Document-const: SIZEOF_FLOAT
00392      *
00393      * size of a float
00394      */
00395     rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float)));
00396 
00397     /* Document-const: SIZEOF_DOUBLE
00398      *
00399      * size of a double
00400      */
00401     rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double)));
00402 
00403     /* Document-const: SIZEOF_SIZE_T
00404      *
00405      * size of a size_t
00406      */
00407     rb_define_const(mFiddle, "SIZEOF_SIZE_T",  INT2NUM(sizeof(size_t)));
00408 
00409     /* Document-const: SIZEOF_SSIZE_T
00410      *
00411      * size of a ssize_t
00412      */
00413     rb_define_const(mFiddle, "SIZEOF_SSIZE_T",  INT2NUM(sizeof(size_t))); /* same as size_t */
00414 
00415     /* Document-const: SIZEOF_PTRDIFF_T
00416      *
00417      * size of a ptrdiff_t
00418      */
00419     rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T",  INT2NUM(sizeof(ptrdiff_t)));
00420 
00421     /* Document-const: SIZEOF_INTPTR_T
00422      *
00423      * size of a intptr_t
00424      */
00425     rb_define_const(mFiddle, "SIZEOF_INTPTR_T",  INT2NUM(sizeof(intptr_t)));
00426 
00427     /* Document-const: SIZEOF_UINTPTR_T
00428      *
00429      * size of a uintptr_t
00430      */
00431     rb_define_const(mFiddle, "SIZEOF_UINTPTR_T",  INT2NUM(sizeof(uintptr_t)));
00432 
00433     /* Document-const: RUBY_FREE
00434      *
00435      * Address of the ruby_xfree() function
00436      */
00437     rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree));
00438 
00439     /* Document-const: BUILD_RUBY_PLATFORM
00440      *
00441      * Platform built against (i.e. "x86_64-linux", etc.)
00442      *
00443      * See also RUBY_PLATFORM
00444      */
00445     rb_define_const(mFiddle, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM));
00446 
00447     rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1);
00448     rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1);
00449     rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1);
00450     rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2);
00451     rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1);
00452 
00453     Init_fiddle_function();
00454     Init_fiddle_closure();
00455     Init_fiddle_handle();
00456     Init_fiddle_pointer();
00457 }
00458 /* vim: set noet sws=4 sw=4: */
00459