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