class Fiddle::Function
Description¶ ↑
A representation of a C function
Examples¶ ↑
'strcpy'¶ ↑
@libc = Fiddle.dlopen "/lib/libc.so.6" #=> #<Fiddle::Handle:0x00000001d7a8d8> f = Fiddle::Function.new( @libc['strcpy'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP) #=> #<Fiddle::Function:0x00000001d8ee00> buff = "000" #=> "000" str = f.call(buff, "123") #=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000> str.to_s => "123"
ABI check¶ ↑
@libc = DL.dlopen "/lib/libc.so.6" #=> #<Fiddle::Handle:0x00000001d7a8d8> f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) #=> #<Fiddle::Function:0x00000001d8ee00> f.abi == Fiddle::Function::DEFAULT #=> true
Constants
Attributes
abi[R]
The ABI of the Function.
name[R]
The name of this function
ptr[R]
The address of this function
Public Class Methods
new(ptr, args, ret_type, abi = DEFAULT)
click to toggle source
Constructs a Function object.
-
ptr
is a referenced function, of a Fiddle::Handle -
args
is an Array of arguments, passed to theptr
function -
ret_type
is the return type of the function -
abi
is the ABI of the function
static VALUE initialize(int argc, VALUE argv[], VALUE self) { ffi_cif * cif; ffi_type **arg_types; ffi_status result; VALUE ptr, args, ret_type, abi, kwds; int i; rb_scan_args(argc, argv, "31:", &ptr, &args, &ret_type, &abi, &kwds); if(NIL_P(abi)) abi = INT2NUM(FFI_DEFAULT_ABI); Check_Type(args, T_ARRAY); rb_iv_set(self, "@ptr", ptr); rb_iv_set(self, "@args", args); rb_iv_set(self, "@return_type", ret_type); rb_iv_set(self, "@abi", abi); if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self); TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif); arg_types = xcalloc(RARRAY_LEN(args) + 1, sizeof(ffi_type *)); for (i = 0; i < RARRAY_LEN(args); i++) { int type = NUM2INT(RARRAY_PTR(args)[i]); arg_types[i] = INT2FFI_TYPE(type); } arg_types[RARRAY_LEN(args)] = NULL; result = ffi_prep_cif ( cif, NUM2INT(abi), RARRAY_LENINT(args), INT2FFI_TYPE(NUM2INT(ret_type)), arg_types); if (result) rb_raise(rb_eRuntimeError, "error creating CIF %d", result); return self; }
Public Instance Methods
call(*args)
click to toggle source
Calls the constructed Function, with
args
For an example see Fiddle::Function
static VALUE function_call(int argc, VALUE argv[], VALUE self) { ffi_cif * cif; fiddle_generic retval; fiddle_generic *generic_args; void **values; VALUE cfunc, types, cPointer; int i; cfunc = rb_iv_get(self, "@ptr"); types = rb_iv_get(self, "@args"); cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); if(argc != RARRAY_LENINT(types)) { rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, RARRAY_LENINT(types)); } TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif); if (rb_safe_level() >= 1) { for (i = 0; i < argc; i++) { VALUE src = argv[i]; if (OBJ_TAINTED(src)) { rb_raise(rb_eSecurityError, "tainted parameter not allowed"); } } } values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *)); generic_args = xcalloc((size_t)argc, (size_t)sizeof(fiddle_generic)); for (i = 0; i < argc; i++) { VALUE type = RARRAY_PTR(types)[i]; VALUE src = argv[i]; if(NUM2INT(type) == TYPE_VOIDP) { if(NIL_P(src)) { src = INT2FIX(0); } else if(cPointer != CLASS_OF(src)) { src = rb_funcall(cPointer, rb_intern("[]"), 1, src); } src = rb_Integer(src); } VALUE2GENERIC(NUM2INT(type), src, &generic_args[i]); values[i] = (void *)&generic_args[i]; } values[argc] = NULL; ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values); rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno)); #if defined(_WIN32) rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno)); #endif xfree(values); xfree(generic_args); return GENERIC2VALUE(rb_iv_get(self, "@return_type"), retval); }
to_i()
click to toggle source
The integer memory location of this function
# File ext/fiddle/lib/fiddle/function.rb, line 13 def to_i ptr.to_i end