Class
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
Read
the C type of the return of the FFI closure
Read
arguments of the FFI closure
Class Methods
ext/fiddle/closure.c
View on GitHub
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 *)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;
}
Construct a new Closure
object.
-
ret
is the C type to be returned -
args
is anArray
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.
Instance Methods
#
ext/fiddle/closure.c
View on GitHub
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);
}
Returns the memory address for this closure