Spec-Zone.ru › Ruby 3.1

класс Fiddle::Closure

Родитель:
Объект

Описание

Обёртка для замыканий FFI для обработки обратных вызовов.

Пример

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

Атрибуты

args[R]

аргументы замыкания FFI

ctype[R]

тип C возвращаемого значения замыкания FFI

Общедоступные методы класса

new(ret, args, abi = Fiddle::DEFAULT) Показать исходный код
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;
}

Создаёт новый объект Closure.

  • ret — тип C, который должен быть возвращён

  • args — Array аргументов, передаваемых функции обратного вызова

  • abi — abi замыкания

Если при подготовке ffi_cif или ffi_prep_closure произошла ошибка, будет поднято исключение RuntimeError.

Общедоступные методы экземпляра

to_i() Показать исходный код
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);
}

Возвращает адрес памяти для этого замыкания

Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API