Ruby  2.0.0p247(2013-06-27revision41674)
function.c
Go to the documentation of this file.
1 #include <fiddle.h>
2 
4 
5 static void
6 deallocate(void *p)
7 {
8  ffi_cif *ptr = p;
9  if (ptr->arg_types) xfree(ptr->arg_types);
10  xfree(ptr);
11 }
12 
13 static size_t
14 function_memsize(const void *p)
15 {
16  /* const */ffi_cif *ptr = (ffi_cif *)p;
17  size_t size = 0;
18 
19  if (ptr) {
20  size += sizeof(*ptr);
21 #if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API
22  size += ffi_raw_size(ptr);
23 #endif
24  }
25  return size;
26 }
27 
29  "fiddle/function",
31 };
32 
33 static VALUE
35 {
36  ffi_cif * cif;
37 
38  return TypedData_Make_Struct(klass, ffi_cif, &function_data_type, cif);
39 }
40 
41 VALUE
42 rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type)
43 {
44  VALUE argv[3];
45 
46  argv[0] = address;
47  argv[1] = arg_types;
48  argv[2] = ret_type;
49 
50  return rb_class_new_instance(3, argv, cFiddleFunction);
51 }
52 
53 static int
55 {
56  if (key == ID2SYM(rb_intern("name"))) {
57  rb_iv_set(self, "@name", value);
58  } else {
59  rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE, key);
60  }
61  return ST_CONTINUE;
62 }
63 
64 static VALUE
66 {
67  ffi_cif * cif;
68  ffi_type **arg_types;
69  ffi_status result;
70  VALUE ptr, args, ret_type, abi, kwds;
71  int i;
72 
73  rb_scan_args(argc, argv, "31:", &ptr, &args, &ret_type, &abi, &kwds);
74  if(NIL_P(abi)) abi = INT2NUM(FFI_DEFAULT_ABI);
75 
76  Check_Type(args, T_ARRAY);
77 
78  rb_iv_set(self, "@ptr", ptr);
79  rb_iv_set(self, "@args", args);
80  rb_iv_set(self, "@return_type", ret_type);
81  rb_iv_set(self, "@abi", abi);
82 
83  if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self);
84 
85  TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
86 
87  arg_types = xcalloc(RARRAY_LEN(args) + 1, sizeof(ffi_type *));
88 
89  for (i = 0; i < RARRAY_LEN(args); i++) {
90  int type = NUM2INT(RARRAY_PTR(args)[i]);
91  arg_types[i] = INT2FFI_TYPE(type);
92  }
93  arg_types[RARRAY_LEN(args)] = NULL;
94 
95  result = ffi_prep_cif (
96  cif,
97  NUM2INT(abi),
98  RARRAY_LENINT(args),
99  INT2FFI_TYPE(NUM2INT(ret_type)),
100  arg_types);
101 
102  if (result)
103  rb_raise(rb_eRuntimeError, "error creating CIF %d", result);
104 
105  return self;
106 }
107 
108 static VALUE
110 {
111  ffi_cif * cif;
113  fiddle_generic *generic_args;
114  void **values;
115  VALUE cfunc, types, cPointer;
116  int i;
117 
118  cfunc = rb_iv_get(self, "@ptr");
119  types = rb_iv_get(self, "@args");
120  cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
121 
122  if(argc != RARRAY_LENINT(types)) {
123  rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
124  argc, RARRAY_LENINT(types));
125  }
126 
127  TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
128 
129  if (rb_safe_level() >= 1) {
130  for (i = 0; i < argc; i++) {
131  VALUE src = argv[i];
132  if (OBJ_TAINTED(src)) {
133  rb_raise(rb_eSecurityError, "tainted parameter not allowed");
134  }
135  }
136  }
137 
138  values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *));
139  generic_args = xcalloc((size_t)argc, (size_t)sizeof(fiddle_generic));
140 
141  for (i = 0; i < argc; i++) {
142  VALUE type = RARRAY_PTR(types)[i];
143  VALUE src = argv[i];
144 
145  if(NUM2INT(type) == TYPE_VOIDP) {
146  if(NIL_P(src)) {
147  src = INT2NUM(0);
148  } else if(cPointer != CLASS_OF(src)) {
149  src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
150  }
151  src = rb_Integer(src);
152  }
153 
154  VALUE2GENERIC(NUM2INT(type), src, &generic_args[i]);
155  values[i] = (void *)&generic_args[i];
156  }
157  values[argc] = NULL;
158 
159  ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values);
160 
161  rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
162 #if defined(_WIN32)
163  rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
164 #endif
165 
166  xfree(values);
167  xfree(generic_args);
168 
169  return GENERIC2VALUE(rb_iv_get(self, "@return_type"), retval);
170 }
171 
172 void
174 {
175  /*
176  * Document-class: Fiddle::Function
177  *
178  * == Description
179  *
180  * A representation of a C function
181  *
182  * == Examples
183  *
184  * === 'strcpy'
185  *
186  * @libc = Fiddle.dlopen "/lib/libc.so.6"
187  * #=> #<Fiddle::Handle:0x00000001d7a8d8>
188  * f = Fiddle::Function.new(
189  * @libc['strcpy'],
190  * [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP],
191  * Fiddle::TYPE_VOIDP)
192  * #=> #<Fiddle::Function:0x00000001d8ee00>
193  * buff = "000"
194  * #=> "000"
195  * str = f.call(buff, "123")
196  * #=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000>
197  * str.to_s
198  * => "123"
199  *
200  * === ABI check
201  *
202  * @libc = DL.dlopen "/lib/libc.so.6"
203  * #=> #<Fiddle::Handle:0x00000001d7a8d8>
204  * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
205  * #=> #<Fiddle::Function:0x00000001d8ee00>
206  * f.abi == Fiddle::Function::DEFAULT
207  * #=> true
208  */
210 
211  /*
212  * Document-const: DEFAULT
213  *
214  * Default ABI
215  *
216  */
217  rb_define_const(cFiddleFunction, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI));
218 
219 #ifdef HAVE_CONST_FFI_STDCALL
220  /*
221  * Document-const: STDCALL
222  *
223  * FFI implementation of WIN32 stdcall convention
224  *
225  */
226  rb_define_const(cFiddleFunction, "STDCALL", INT2NUM(FFI_STDCALL));
227 #endif
228 
230 
231  /*
232  * Document-method: call
233  *
234  * Calls the constructed Function, with +args+
235  *
236  * For an example see Fiddle::Function
237  *
238  */
240 
241  /*
242  * Document-method: new
243  * call-seq: new(ptr, args, ret_type, abi = DEFAULT)
244  *
245  * Constructs a Function object.
246  * * +ptr+ is a referenced function, of a Fiddle::Handle
247  * * +args+ is an Array of arguments, passed to the +ptr+ function
248  * * +ret_type+ is the return type of the function
249  * * +abi+ is the ABI of the function
250  *
251  */
252  rb_define_method(cFiddleFunction, "initialize", initialize, -1);
253 }
254 /* vim: set noet sws=4 sw=4: */
#define VALUE2GENERIC(_type, _src, _dst)
Definition: conversions.h:31
RARRAY_PTR(q->result)[0]
#define TYPE_VOIDP
Definition: fiddle.h:113
VALUE mFiddle
Definition: fiddle.c:3
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1756
Win32OLEIDispatch * p
Definition: win32ole.c:786
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:2586
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1871
ssize_t i
Definition: bigdecimal.c:5655
static VALUE initialize(int argc, VALUE argv[], VALUE self)
Definition: function.c:65
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2578
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define OBJ_TAINTED(x)
#define CLASS_OF(v)
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
#define T_ARRAY
#define xfree
#define NUM2PTR(x)
Definition: dl.h:169
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:545
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
VALUE rb_eSecurityError
Definition: error.c:520
static void deallocate(void *p)
Definition: function.c:6
#define ID2SYM(x)
VALUE VALUE args
Definition: tcltklib.c:2561
void rb_hash_foreach(VALUE, int(*)(ANYARGS), VALUE)
Definition: hash.c:200
#define TypedData_Get_Struct(obj, type, data_type, sval)
#define RARRAY_LEN(a)
VALUE rb_eRuntimeError
Definition: error.c:510
#define Check_Type(v, t)
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2197
static VALUE function_call(int argc, VALUE argv[], VALUE self)
Definition: function.c:109
VALUE cFiddleFunction
Definition: function.c:3
static int parse_keyword_arg_i(VALUE key, VALUE value, VALUE self)
Definition: function.c:54
#define INT2FFI_TYPE(_type)
Definition: conversions.h:32
static int VALUE key
Definition: tkutil.c:265
VALUE * argv
Definition: tcltklib.c:1971
int errno
q result
Definition: tcltklib.c:7070
volatile VALUE value
Definition: tcltklib.c:9442
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1566
VALUE retval
Definition: tcltklib.c:7830
int type
Definition: tcltklib.c:111
int argc
Definition: tcltklib.c:1970
static VALUE allocate(VALUE klass)
Definition: function.c:34
return ptr
Definition: tcltklib.c:784
VALUE rb_Integer(VALUE)
Definition: object.c:2469
VALUE src
Definition: tcltklib.c:7953
int size
Definition: encoding.c:52
VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type)
Definition: function.c:42
#define TypedData_Make_Struct(klass, type, data_type, sval)
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
#define RARRAY_LENINT(ary)
klass
Definition: tcltklib.c:3504
#define INT2NUM(x)
const rb_data_type_t function_data_type
Definition: function.c:28
#define GENERIC2VALUE(_type, _retval)
Definition: conversions.h:33
#define rb_safe_level()
Definition: tcltklib.c:94
#define NUM2INT(x)
#define PRIsVALUE
#define xcalloc
unsigned long VALUE
Definition: ripper.y:104
void Init_fiddle_function(void)
Definition: function.c:173
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:103
static size_t function_memsize(const void *p)
Definition: function.c:14
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1340
VALUE rb_eArgError
Definition: error.c:512