Ruby  1.9.3p547(2014-05-14revision45962)
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 static VALUE
43 {
44  ffi_cif * cif;
45  ffi_type **arg_types;
46  ffi_status result;
47  VALUE ptr, args, ret_type, abi;
48  int i;
49 
50  rb_scan_args(argc, argv, "31", &ptr, &args, &ret_type, &abi);
51  if(NIL_P(abi)) abi = INT2NUM(FFI_DEFAULT_ABI);
52 
53  Check_Type(args, T_ARRAY);
54 
55  rb_iv_set(self, "@ptr", ptr);
56  rb_iv_set(self, "@args", args);
57  rb_iv_set(self, "@return_type", ret_type);
58  rb_iv_set(self, "@abi", abi);
59 
60  TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
61 
62  arg_types = xcalloc(RARRAY_LEN(args) + 1, sizeof(ffi_type *));
63 
64  for (i = 0; i < RARRAY_LEN(args); i++) {
65  int type = NUM2INT(RARRAY_PTR(args)[i]);
66  arg_types[i] = INT2FFI_TYPE(type);
67  }
68  arg_types[RARRAY_LEN(args)] = NULL;
69 
70  result = ffi_prep_cif (
71  cif,
72  NUM2INT(abi),
73  RARRAY_LENINT(args),
74  INT2FFI_TYPE(NUM2INT(ret_type)),
75  arg_types);
76 
77  if (result)
78  rb_raise(rb_eRuntimeError, "error creating CIF %d", result);
79 
80  return self;
81 }
82 
83 static VALUE
85 {
86  ffi_cif * cif;
87  fiddle_generic retval;
88  fiddle_generic *generic_args;
89  void **values;
90  VALUE cfunc, types, cPointer;
91  int i;
92 
93  cfunc = rb_iv_get(self, "@ptr");
94  types = rb_iv_get(self, "@args");
95  cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
96 
97  if(argc != RARRAY_LENINT(types)) {
98  rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
99  argc, RARRAY_LENINT(types));
100  }
101 
102  TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
103 
104  if (rb_safe_level() >= 1) {
105  for (i = 0; i < argc; i++) {
106  VALUE src = argv[i];
107  if (OBJ_TAINTED(src)) {
108  rb_raise(rb_eSecurityError, "tainted parameter not allowed");
109  }
110  }
111  }
112 
113  values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *));
114  generic_args = xcalloc((size_t)argc, (size_t)sizeof(fiddle_generic));
115 
116  for (i = 0; i < argc; i++) {
117  VALUE type = RARRAY_PTR(types)[i];
118  VALUE src = argv[i];
119 
120  if(NUM2INT(type) == TYPE_VOIDP) {
121  if(NIL_P(src)) {
122  src = INT2NUM(0);
123  } else if(cPointer != CLASS_OF(src)) {
124  src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
125  }
126  src = rb_Integer(src);
127  }
128 
129  VALUE2GENERIC(NUM2INT(type), src, &generic_args[i]);
130  values[i] = (void *)&generic_args[i];
131  }
132  values[argc] = NULL;
133 
134  ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values);
135 
136  rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
137 #if defined(_WIN32)
138  rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
139 #endif
140 
141  xfree(values);
142  xfree(generic_args);
143 
144  return GENERIC2VALUE(rb_iv_get(self, "@return_type"), retval);
145 }
146 
147 void
149 {
150  /*
151  * Document-class: Fiddle::Function
152  *
153  * == Description
154  *
155  * A representation of a C function
156  *
157  * == Examples
158  *
159  * === 'strcpy'
160  *
161  * @libc = DL.dlopen "/lib/libc.so.6"
162  * => #<DL::Handle:0x00000001d7a8d8>
163  * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
164  * => #<Fiddle::Function:0x00000001d8ee00>
165  * buff = "000"
166  * => "000"
167  * str = f.call(buff, "123")
168  * => #<DL::CPtr:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000>
169  * str.to_s
170  * => "123"
171  *
172  * === ABI check
173  *
174  * @libc = DL.dlopen "/lib/libc.so.6"
175  * => #<DL::Handle:0x00000001d7a8d8>
176  * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
177  * => #<Fiddle::Function:0x00000001d8ee00>
178  * f.abi == Fiddle::Function::DEFAULT
179  * => true
180  */
182 
183  /*
184  * Document-const: DEFAULT
185  *
186  * Default ABI
187  *
188  */
189  rb_define_const(cFiddleFunction, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI));
190 
191 #ifdef HAVE_CONST_FFI_STDCALL
192  /*
193  * Document-const: STDCALL
194  *
195  * FFI implementation of WIN32 stdcall convention
196  *
197  */
198  rb_define_const(cFiddleFunction, "STDCALL", INT2NUM(FFI_STDCALL));
199 #endif
200 
202 
203  /*
204  * Document-method: call
205  *
206  * Calls the constructed Function, with +args+
207  *
208  * For an example see Fiddle::Function
209  *
210  */
212 
213  /*
214  * Document-method: new
215  * call-seq: new(ptr, args, ret_type, abi = DEFAULT)
216  *
217  * Constructs a Function object.
218  * * +ptr+ is a referenced function, of a DL::Handle
219  * * +args+ is an Array of arguments, passed to the +ptr+ function
220  * * +ret_type+ is the return type of the function
221  * * +abi+ is the ABI of the function
222  *
223  */
224  rb_define_method(cFiddleFunction, "initialize", initialize, -1);
225 }
226 /* vim: set noet sws=4 sw=4: */
#define VALUE2GENERIC(_type, _src, _dst)
Definition: conversions.h:31
#define TYPE_VOIDP
Definition: fiddle.h:89
VALUE mFiddle
Definition: fiddle.c:3
int i
Definition: win32ole.c:776
#define NUM2INT(x)
Definition: ruby.h:536
#define CLASS_OF(v)
Definition: ruby.h:376
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:840
static VALUE initialize(int argc, VALUE argv[], VALUE self)
Definition: function.c:42
static VALUE INT2NUM(int v)
Definition: ruby.h:981
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:638
#define NUM2PTR(x)
Definition: dl.h:178
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:515
#define Check_Type(v, t)
Definition: ruby.h:459
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1574
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define RARRAY_LEN(ARRAY)
Definition: generator.h:39
VALUE rb_eSecurityError
Definition: error.c:476
#define T_ARRAY
Definition: ruby.h:420
static void deallocate(void *p)
Definition: function.c:6
#define OBJ_TAINTED(x)
Definition: ruby.h:963
Win32OLEIDispatch * p
Definition: win32ole.c:778
int args
Definition: win32ole.c:777
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1246
VALUE rb_eRuntimeError
Definition: error.c:466
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2220
static VALUE function_call(int argc, VALUE argv[], VALUE self)
Definition: function.c:84
#define NIL_P(v)
Definition: ruby.h:374
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:1923
VALUE cFiddleFunction
Definition: function.c:3
int argc
Definition: ruby.c:120
VALUE rb_Integer(VALUE)
Definition: object.c:2193
#define INT2FFI_TYPE(_type)
Definition: conversions.h:32
Definition: error.c:344
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1635
int errno
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:2228
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1416
int type
Definition: tcltklib.c:107
unsigned long VALUE
Definition: ruby.h:88
static VALUE allocate(VALUE klass)
Definition: function.c:34
static VALUE result
Definition: nkf.c:40
#define RARRAY_PTR(ARRAY)
Definition: generator.h:36
#define RARRAY_LENINT(ary)
Definition: ruby.h:718
void xfree(void *)
int size
Definition: encoding.c:51
const rb_data_type_t function_data_type
Definition: function.c:28
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:829
#define GENERIC2VALUE(_type, _retval)
Definition: conversions.h:33
#define rb_safe_level()
Definition: tcltklib.c:90
void Init_fiddle_function(void)
Definition: function.c:148
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:107
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:1210
VALUE rb_eArgError
Definition: error.c:468
char ** argv
Definition: ruby.c:121
#define xcalloc
Definition: defines.h:66