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