Class: Fiddle::Closure
| Relationships & Source Files | |
| Namespace Children | |
| Classes: | |
| Extension / Inclusion / Inheritance Descendants | |
| Subclasses: | |
| Inherits: | Object | 
| Defined in: | ext/fiddle/closure.c, ext/fiddle/pinned.c, ext/fiddle/lib/fiddle/closure.rb, ext/fiddle/lib/fiddle/ffi_backend.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
- 
    
      .create(*args)  
    
    Create a new closure. 
- 
    
      .new(object)  ⇒ Pinned 
    
    constructor
    Alias for Pinned.new. 
Instance Attribute Summary
- 
    
      #args  
    
    readonly
    arguments of the FFI closure. 
- 
    
      #ctype  
    
    readonly
    the C type of the return of the FFI closure. 
- 
    
      #freed?  ⇒ Boolean 
    
    readonly
    Whether this closure was freed explicitly. 
Instance Method Summary
- 
    
      #free  
    
    Free this closure explicitly. 
- #initialize(ret, args, abi = Function::DEFAULT) ⇒ Closure constructor
- 
    
      #to_i  
    
    Returns the memory address for this closure. 
- #to_ptr
Constructor Details
.new(object) ⇒ Pinned
Alias for Pinned.new.
    #initialize(ret, args, abi = Function::DEFAULT)  ⇒ Closure 
  
# File 'ext/fiddle/lib/fiddle/ffi_backend.rb', line 181
def initialize(ret, args, abi = Function::DEFAULT) raise TypeError.new "invalid argument types" unless args.is_a?(Array) @ctype, @args = ret, args ffi_args = @args.map { |t| Fiddle::FFIBackend.to_ffi_type(t) } if ffi_args.size == 1 && ffi_args[0] == FFI::Type::Builtin::VOID ffi_args = [] end return_type = Fiddle::FFIBackend.to_ffi_type(@ctype) raise "#{self.class} must implement #call" unless respond_to?(:call) callable = method(:call) @function = FFI::Function.new(return_type, ffi_args, callable, convention: abi) @freed = false end
Class Method Details
.create(*args)
Create a new closure. If a block is given, the created closure is automatically freed after the given block is executed.
The all given arguments are passed to .new. So using this method without block equals to .new.
Example
Fiddle::Closure.create(TYPE_INT, [TYPE_INT]) do |closure|
  # closure is freed automatically when this block is finished.
endInstance Attribute Details
#args (readonly)
arguments of the FFI closure
# File 'ext/fiddle/lib/fiddle/closure.rb', line 34
attr_reader :args
#ctype (readonly)
the C type of the return of the FFI closure
# File 'ext/fiddle/lib/fiddle/closure.rb', line 31
attr_reader :ctype
    #freed?  ⇒ Boolean  (readonly)
  
Whether this closure was freed explicitly.
# File 'ext/fiddle/closure.c', line 381
static VALUE
closure_freed_p(VALUE self)
{
    fiddle_closure *closure;
    TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
    return closure ? RUBY_Qfalse : RUBY_Qtrue;
}
  Instance Method Details
#free
Free this closure explicitly. You can’t use this closure anymore.
If this closure is already freed, this does nothing.
# File 'ext/fiddle/closure.c', line 369
static VALUE
closure_free(VALUE self)
{
    fiddle_closure *closure;
    TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
    if (closure) {
        dealloc(closure);
        RTYPEDDATA_DATA(self) = NULL;
    }
    return RUBY_Qnil;
}
  #to_i
Returns the memory address for this closure.
# File 'ext/fiddle/closure.c', line 362
static VALUE
to_i(VALUE self)
{
    fiddle_closure *closure = get_raw(self);
    return PTR2NUM(closure->code);
}
  #to_ptr
[ GitHub ]# File 'ext/fiddle/lib/fiddle/ffi_backend.rb', line 196
def to_ptr @function end