Class: Fiddle::Closure
| Relationships & Source Files | |
| Namespace Children | |
| Classes: | |
| Extension / Inclusion / Inheritance Descendants | |
| Subclasses: | |
| Inherits: | Object | 
| Defined in: | ext/fiddle/closure.c, ext/fiddle/lib/fiddle/closure.rb | 
Overview
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
   #=> 10Class Method Summary
- 
    
      .new(ret, args, abi = Fiddle::DEFAULT)  
    
    constructor
    Construct a new Closureobject.
Instance Attribute Summary
Instance Method Summary
- 
    
      #to_i  
    
    Returns the memory address for this closure. 
Constructor Details
.new(ret, args, abi = Fiddle::DEFAULT)
Construct a new Closure object.
- 
retis the C type to be returned
- 
#args is an Array of arguments, passed to the callback function 
- 
abiis 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.
# File 'ext/fiddle/closure.c', line 218
static VALUE
initialize(int rbargc, VALUE argv[], VALUE self)
{
    VALUE ret;
    VALUE 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 *));
    for (i = 0; i < argc; i++) {
        int type = NUM2INT(RARRAY_AREF(args, i));
        cl->argv[i] = INT2FFI_TYPE(type);
    }
    cl->argv[argc] = NULL;
    rb_iv_set(self, "@ctype", ret);
    rb_iv_set(self, "@args", args);
    cif = &cl->cif;
    pcl = cl->pcl;
    result = ffi_prep_cif(cif, NUM2INT(abi), argc,
                INT2FFI_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;
}
  Instance Attribute Details
#args (readonly)
arguments of the FFI closure
# File 'ext/fiddle/lib/fiddle/closure.rb', line 9
attr_reader :args
#ctype (readonly)
the C type of the return of the FFI closure
# File 'ext/fiddle/lib/fiddle/closure.rb', line 6
attr_reader :ctype
Instance Method Details
#to_i
Returns the memory address for this closure
# File 'ext/fiddle/closure.c', line 278
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);
}