# 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

create (*args) { |closure| ... }
Source

    # File ext/fiddle/lib/fiddle/closure.rb, line 16
    def create(*args)
      if block_given?
        closure = new(*args)
        begin
          yield(closure)
        ensure
          closure.free
        end
      else
        new(*args)
      end
    end

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 `Fiddle::Closure.new`. So using this method without block equals to `Fiddle::Closure.new`.

## Example¶ ↑

    Fiddle::Closure.create(TYPE_INT, [TYPE_INT]) do |closure|
      # closure is freed automatically when this block is finished.
    end

new (ret, args, abi = Function::DEFAULT)
Source

    # 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

new(ret, args, abi = Fiddle::DEFAULT)
Source

    static VALUE
    initialize(int argc, VALUE *argv, VALUE self)
    {
        initialize_data data;
        data.self = self;
        data.argc = argc;
        data.argv = argv;
        return rb_rescue(initialize_body, (VALUE)&data,
                         initialize_rescue, (VALUE)&data);
    }

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.

### Public Instance Methods

free ()
Source

    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;
    }

Free this closure explicitly. You can’t use this closure anymore.

If this closure is already freed, this does nothing.

freed? ()
Source

    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;
    }

Whether this closure was freed explicitly.

to_i ()
Source

    static VALUE
    to_i(VALUE self)
    {
        fiddle_closure *closure = get_raw(self);
        return PTR2NUM(closure->code);
    }

Returns the memory address for this closure.

to_ptr ()
Source

    # File ext/fiddle/lib/fiddle/ffi_backend.rb, line 196
    def to_ptr
      @function
    end