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

DEFAULT

DEFAULT

Default ABI

STDCALL

STDCALL

FFI implementation of WIN32 stdcall convention

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 the ptr 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