class Fiddle::Closure
Description¶ ↑
An FFI closure wrapper, for handling callbacks.
Example¶ ↑
closure = Class.new(Fiddle::Closure) { def call 10 end }.new(Fiddle::TYPE_INT, []) #=> #<#<Class:0x0000000150d308>:0x0000000150d240> func = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT) #=> #<Fiddle::Function:0x00000001516e58> func.call #=> 10
Attributes
args[R]
arguments of the FFI closure
ctype[R]
the C type of the return of the FFI closure
Public Class Methods
new(ret, args, abi = Fiddle::DEFAULT)
click to toggle source
Construct a new Closure
object.
-
ret
is the C type to be returned -
args
is an Array of arguments, passed to the callback function -
abi
is the abi of the closure
If there is an error in preparing the ffi_cif or ffi_prep_closure, then a RuntimeError will be raised.
static VALUE initialize(int rbargc, VALUE argv[], VALUE self) { VALUE ret; VALUE args; VALUE normalized_args; VALUE abi; fiddle_closure * cl; ffi_cif * cif; ffi_closure *pcl; ffi_status result; int i, argc; if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi)) abi = INT2NUM(FFI_DEFAULT_ABI); Check_Type(args, T_ARRAY); argc = RARRAY_LENINT(args); TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl); cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *)); normalized_args = rb_ary_new_capa(argc); for (i = 0; i < argc; i++) { VALUE arg = rb_fiddle_type_ensure(RARRAY_AREF(args, i)); rb_ary_push(normalized_args, arg); cl->argv[i] = rb_fiddle_int_to_ffi_type(NUM2INT(arg)); } cl->argv[argc] = NULL; ret = rb_fiddle_type_ensure(ret); rb_iv_set(self, "@ctype", ret); rb_iv_set(self, "@args", normalized_args); cif = &cl->cif; pcl = cl->pcl; result = ffi_prep_cif(cif, NUM2INT(abi), argc, rb_fiddle_int_to_ffi_type(NUM2INT(ret)), cl->argv); if (FFI_OK != result) rb_raise(rb_eRuntimeError, "error prepping CIF %d", result); #if USE_FFI_CLOSURE_ALLOC result = ffi_prep_closure_loc(pcl, cif, callback, (void *)self, cl->code); #else result = ffi_prep_closure(pcl, cif, callback, (void *)(data->self)); cl->code = (void *)pcl; i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC); if (i) { rb_sys_fail("mprotect"); } #endif if (FFI_OK != result) rb_raise(rb_eRuntimeError, "error prepping closure %d", result); return self; }
Public Instance Methods
to_i()
click to toggle source
Returns the memory address for this closure
static VALUE to_i(VALUE self) { fiddle_closure * cl; void *code; TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl); code = cl->code; return PTR2NUM(code); }