Spec-Zone.ru › Ruby 3

класс Fiddle::Pointer

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

Fiddle::Pointer — это класс для работы с указателями C

Публичные методы класса

Fiddle::Pointer[val] → cptr Показать исходный код
to_ptr(val) → cptr
static VALUE
rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
{
    VALUE ptr, wrap = val, vptr;

    if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
        rb_io_t *fptr;
        FILE *fp;
        GetOpenFile(val, fptr);
        fp = rb_io_stdio_file(fptr);
        ptr = rb_fiddle_ptr_new(fp, 0, NULL);
    }
    else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
        char *str = StringValuePtr(val);
        ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL);
    }
    else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){
        if (rb_obj_is_kind_of(vptr, rb_cPointer)){
            ptr = vptr;
            wrap = 0;
        }
        else{
            rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object");
        }
    }
    else{
        VALUE num = rb_Integer(val);
        if (num == val) wrap = 0;
        ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL);
    }
    if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap;
    return ptr;
}

Получить базовый указатель для объекта Ruby val и вернуть его как объект Fiddle::Pointer.

Fiddle::Pointer.malloc(size, freefunc = nil) → экземпляр указателя fiddle Показать исходный код
Fiddle::Pointer.malloc(size, freefunc) { |pointer| ... } → ...
static VALUE
rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
{
    VALUE size, sym, obj, wrap = 0;
    long s;
    freefunc_t f;

    switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
      case 1:
        s = NUM2LONG(size);
        f = NULL;
        break;
      case 2:
        s = NUM2LONG(size);
        f = get_freefunc(sym, &wrap);
        break;
      default:
        rb_bug("rb_fiddle_ptr_s_malloc");
    }

    obj = rb_fiddle_ptr_malloc(klass, s,f);
    if (wrap) RPTR_DATA(obj)->wrap[1] = wrap;

    if (rb_block_given_p()) {
        if (!f) {
            rb_raise(rb_eArgError, "a free function must be supplied to Fiddle::Pointer.malloc when it is called with a block");
        }
        return rb_ensure(rb_yield, obj, rb_fiddle_ptr_call_free, obj);
    } else {
        return obj;
    }
}

Примеры

# Automatically freeing the pointer when the block is exited - recommended
Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) do |pointer|
  ...
end

# Manually freeing but relying on the garbage collector otherwise
pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
...
pointer.call_free

# Relying on the garbage collector - may lead to unlimited memory allocated before freeing any, but safe
pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
...

# Only manually freeing
pointer = Fiddle::Pointer.malloc(size)
begin
  ...
ensure
  Fiddle.free pointer
end

# No free function and no call to free - the native memory will leak if the pointer is garbage collected
pointer = Fiddle::Pointer.malloc(size)
...

Выделить size байтов памяти и связать его с необязательной freefunc.

Если блок предоставлен, указатель будет передан в блок вместо возврата, а возвращаемое значение блока будет возвращено. Блок должен быть предоставлен, если предоставлен блок freefunc.

Если freefunc предоставлен, он будет вызван один раз, когда указатель будет собран сборщиком мусора или когда блок будет оставлен, если предоставлен блок, или когда пользователь вызовет call_free, в зависимости от того, что произойдет первым. freefunc должен быть адресом, указывающим на функцию или экземпляр Fiddle::Function.

Fiddle::Pointer.new(address) → fiddle_cptr Показать исходный код
new(address, size) → fiddle_cptr
new(address, size, freefunc) → fiddle_cptr
static VALUE
rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self)
{
    VALUE ptr, sym, size, wrap = 0, funcwrap = 0;
    struct ptr_data *data;
    void *p = NULL;
    freefunc_t f = NULL;
    long s = 0;

    if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) {
        VALUE addrnum = rb_Integer(ptr);
        if (addrnum != ptr) wrap = ptr;
        p = NUM2PTR(addrnum);
    }
    if (argc >= 2) {
        s = NUM2LONG(size);
    }
    if (argc >= 3) {
        f = get_freefunc(sym, &funcwrap);
    }

    if (p) {
        TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
        if (data->ptr && data->free) {
            /* Free previous memory. Use of inappropriate initialize may cause SEGV. */
            (*(data->free))(data->ptr);
        }
        data->wrap[0] = wrap;
        data->wrap[1] = funcwrap;
        data->ptr  = p;
        data->size = s;
        data->free = f;
    }

    return Qnil;
}

Создать новый указатель на address с необязательной size и freefunc.

freefunc будет вызван, когда экземпляр будет собран сборщиком мусора.

Fiddle::Pointer[val] → cptr Показать исходный код
to_ptr(val) → cptr
static VALUE
rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
{
    VALUE ptr, wrap = val, vptr;

    if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
        rb_io_t *fptr;
        FILE *fp;
        GetOpenFile(val, fptr);
        fp = rb_io_stdio_file(fptr);
        ptr = rb_fiddle_ptr_new(fp, 0, NULL);
    }
    else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
        char *str = StringValuePtr(val);
        ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL);
    }
    else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){
        if (rb_obj_is_kind_of(vptr, rb_cPointer)){
            ptr = vptr;
            wrap = 0;
        }
        else{
            rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object");
        }
    }
    else{
        VALUE num = rb_Integer(val);
        if (num == val) wrap = 0;
        ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL);
    }
    if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap;
    return ptr;
}

Получить базовый указатель для объекта Ruby val и вернуть его как объект Fiddle::Pointer.

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

ptr + n → new cptr Показать исходный код
static VALUE
rb_fiddle_ptr_plus(VALUE self, VALUE other)
{
    void *ptr;
    long num, size;

    ptr = rb_fiddle_ptr2cptr(self);
    size = RPTR_DATA(self)->size;
    num = NUM2LONG(other);
    return rb_fiddle_ptr_new((char *)ptr + num, size - num, 0);
}

Возвращает новый экземпляр указателя, сдвинутый на n байта.

Возвращает новый экземпляр Fiddle::Pointer, являющийся разыменованным указателем для данного указателя.

Аналогично оператору звездочки в C.

Псевдоним для: ptr
ptr - n → new cptr Показать исходный код
static VALUE
rb_fiddle_ptr_minus(VALUE self, VALUE other)
{
    void *ptr;
    long num, size;

    ptr = rb_fiddle_ptr2cptr(self);
    size = RPTR_DATA(self)->size;
    num = NUM2LONG(other);
    return rb_fiddle_ptr_new((char *)ptr - num, size + num, 0);
}

Возвращает новый экземпляр указателя, смещённый назад на n байта.

Возвращает новый экземпляр Fiddle::Pointer, являющийся указателем ссылки для данного указателя.

Аналогично оператору амперсанда в C.

Псевдоним для: ref
ptr <=> other → -1, 0, 1, or nil Показать исходный код
static VALUE
rb_fiddle_ptr_cmp(VALUE self, VALUE other)
{
    void *ptr1, *ptr2;
    SIGNED_VALUE diff;

    if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qnil;

    ptr1 = rb_fiddle_ptr2cptr(self);
    ptr2 = rb_fiddle_ptr2cptr(other);
    diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2;
    if (!diff) return INT2FIX(0);
    return diff > 0 ? INT2NUM(1) : INT2NUM(-1);
}

Возвращает -1, если меньше, 0, если равно, 1, если больше other.

Возвращает nil, если ptr нельзя сравнить с other.

ptr == other → true или false Показать исходный код
static VALUE
rb_fiddle_ptr_eql(VALUE self, VALUE other)
{
    void *ptr1, *ptr2;

    if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qfalse;

    ptr1 = rb_fiddle_ptr2cptr(self);
    ptr2 = rb_fiddle_ptr2cptr(other);

    return ptr1 == ptr2 ? Qtrue : Qfalse;
}

Возвращает true, если other оборачивает тот же указатель, в противном случае возвращает false.

Также псевдоним: eql?
ptr[index] → целое число Показать исходный код
ptr[start, length] → строка
static VALUE
rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
{
    VALUE arg0, arg1;
    VALUE retval = Qnil;
    size_t offset, len;
    struct ptr_data *data;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
    switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
      case 1:
        offset = NUM2ULONG(arg0);
        retval = INT2NUM(*((char *)data->ptr + offset));
        break;
      case 2:
        offset = NUM2ULONG(arg0);
        len    = NUM2ULONG(arg1);
        retval = rb_str_new((char *)data->ptr + offset, len);
        break;
      default:
        rb_bug("rb_fiddle_ptr_aref()");
    }
    return retval;
}

Возвращает целое число, хранящееся по индексу.

Если заданы start и length, возвращается строка, содержащая байты от start длиной length.

ptr[index] = int → int Показать исходный код
ptr[start, length] = строка или cptr или адрес → строка или dl_cptr или адрес
static VALUE
rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self)
{
    VALUE arg0, arg1, arg2;
    VALUE retval = Qnil;
    size_t offset, len;
    void *mem;
    struct ptr_data *data;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
    switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
      case 2:
        offset = NUM2ULONG(arg0);
        ((char*)data->ptr)[offset] = NUM2UINT(arg1);
        retval = arg1;
        break;
      case 3:
        offset = NUM2ULONG(arg0);
        len    = NUM2ULONG(arg1);
        if (RB_TYPE_P(arg2, T_STRING)) {
            mem = StringValuePtr(arg2);
        }
        else if( rb_obj_is_kind_of(arg2, rb_cPointer) ){
            mem = rb_fiddle_ptr2cptr(arg2);
        }
        else{
            mem    = NUM2PTR(arg2);
        }
        memcpy((char *)data->ptr + offset, mem, len);
        retval = arg2;
        break;
      default:
        rb_bug("rb_fiddle_ptr_aset()");
    }
    return retval;
}

Set значение по index на int.

Или, задайте память по start до length содержимым string, памятью из dl_cptr, или памятью, на которую указывает адрес памяти addr.

call_free → nil Показать исходный код
static VALUE
rb_fiddle_ptr_call_free(VALUE self)
{
    struct ptr_data *pdata;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
    fiddle_ptr_free_ptr(pdata);
    return Qnil;
}

Вызов функции освобождения для этого указателя. Вызов более одного раза ничего не сделает. Ничего не делает, если прикреплена никакая функция освобождения.

eql?(other) → true или false

Возвращает true, если other оборачивает тот же указатель, в противном случае возвращает false.

Псевдоним для: ==
free → Fiddle::Function Показать исходный код
static VALUE
rb_fiddle_ptr_free_get(VALUE self)
{
    struct ptr_data *pdata;
    VALUE address;
    VALUE arg_types;
    VALUE ret_type;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);

    if (!pdata->free)
        return Qnil;

    address = PTR2NUM(pdata->free);
    ret_type = INT2NUM(TYPE_VOID);
    arg_types = rb_ary_new();
    rb_ary_push(arg_types, INT2NUM(TYPE_VOIDP));

    return rb_fiddle_new_function(address, arg_types, ret_type);
}

Получить функцию освобождения для этого указателя.

Возвращает новый экземпляр Fiddle::Function.

См. Fiddle::Function.new

free=(function) Показать исходный код
static VALUE
rb_fiddle_ptr_free_set(VALUE self, VALUE val)
{
    struct ptr_data *data;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    data->free = get_freefunc(val, &data->wrap[1]);

    return Qnil;
}

Set функцию освобождения для этого указателя на function в заданной Fiddle::Function.

freed? → bool Показать исходный код
static VALUE
rb_fiddle_ptr_freed_p(VALUE self)
{
    struct ptr_data *pdata;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
    return pdata->freed ? Qtrue : Qfalse;
}

Возвращает, была ли вызвана функция освобождения для этого указателя.

inspect Показать исходный код
static VALUE
rb_fiddle_ptr_inspect(VALUE self)
{
    struct ptr_data *data;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>",
                      RB_OBJ_CLASSNAME(self), (void *)data, data->ptr, data->size, (void *)data->free);
}

Возвращает строку, отформатированную для удобного чтения представления внутреннего состояния указателя.

null? Показать исходный код
static VALUE
rb_fiddle_ptr_null_p(VALUE self)
{
    struct ptr_data *data;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return data->ptr ? Qfalse : Qtrue;
}

Возвращает true, если это нулевой указатель.

ptr Показать исходный код
static VALUE
rb_fiddle_ptr_ptr(VALUE self)
{
    struct ptr_data *data;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return rb_fiddle_ptr_new(*((void**)(data->ptr)),0,0);
}

Возвращает новый экземпляр Fiddle::Pointer, являющийся разыменованным указателем для данного указателя.

Аналогично оператору звездочки в C.

Также псевдоним: +@
ref Показать исходный код
static VALUE
rb_fiddle_ptr_ref(VALUE self)
{
    struct ptr_data *data;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return rb_fiddle_ptr_new(&(data->ptr),0,0);
}

Возвращает новый экземпляр Fiddle::Pointer, являющийся указателем ссылки для данного указателя.

Аналогично оператору амперсанда в C.

Также псевдоним: -@
size Показать исходный код
static VALUE
rb_fiddle_ptr_size_get(VALUE self)
{
    return LONG2NUM(RPTR_DATA(self)->size);
}

Получить размер этого указателя.

size=(size) Показать исходный код
static VALUE
rb_fiddle_ptr_size_set(VALUE self, VALUE size)
{
    RPTR_DATA(self)->size = NUM2LONG(size);
    return size;
}

Set размер этого указателя на size

to_i Показать исходный код
static VALUE
rb_fiddle_ptr_to_i(VALUE self)
{
    struct ptr_data *data;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return PTR2NUM(data->ptr);
}

Возвращает целое число расположения памяти этого указателя.

Также псевдоним: to_int

Возвращает целое число расположения памяти этого указателя.

Псевдоним для: to_i
to_s → строка Показать исходный код
to_s(len) → строка
static VALUE
rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self)
{
    struct ptr_data *data;
    VALUE arg1, val;
    int len;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    switch (rb_scan_args(argc, argv, "01", &arg1)) {
      case 0:
        val = rb_str_new2((char*)(data->ptr));
        break;
      case 1:
        len = NUM2INT(arg1);
        val = rb_str_new((char*)(data->ptr), len);
        break;
      default:
        rb_bug("rb_fiddle_ptr_to_s");
    }

    return val;
}

Возвращает содержимое указателя в виде строки.

Когда вызывается без аргументов, этот метод вернёт содержимое до первого нулевого байта.

При вызове с len, будет возвращена строка из len байтов.

См. to_str

to_str → строка Показать исходный код
to_str(len) → строка
static VALUE
rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self)
{
    struct ptr_data *data;
    VALUE arg1, val;
    int len;

    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    switch (rb_scan_args(argc, argv, "01", &arg1)) {
      case 0:
        val = rb_str_new((char*)(data->ptr),data->size);
        break;
      case 1:
        len = NUM2INT(arg1);
        val = rb_str_new((char*)(data->ptr), len);
        break;
      default:
        rb_bug("rb_fiddle_ptr_to_str");
    }

    return val;
}

Возвращает содержимое указателя в виде строки.

При вызове без аргументов этот метод вернёт содержимое длиной этого указателя size.

При вызове с len, будет возвращена строка из len байтов.

См. to_s

to_value Показать исходный код
static VALUE
rb_fiddle_ptr_to_value(VALUE self)
{
    struct ptr_data *data;
    TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
    return (VALUE)(data->ptr);
}

Приведение этого указателя к объекту руби.

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

Spec-Zone.ru

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