Spec-Zone.ru › Ruby 3.2

класс 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);
        wrap = 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);
        wrap = 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 Show source
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 байт.

ptr

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

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

Псевдоним для: ptr
ptr - n → new cptr Show source
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 байт.

ref

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

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

Псевдоним для: ref
ptr <=> other → -1, 0, 1, or nil Show source
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 or false Show source
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] → an_integer Show source
ptr[start, length] → a_string
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;
}

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

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

ptr[index] = int → int Show source
ptr[start, length] = string or cptr or addr → string or dl_cptr or addr
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 Show source
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 or false

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

Псевдоним для: ==
free → Fiddle::Function Show source
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) Show source
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 Show source
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 Show source
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? Show source
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 Show source
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 Show source
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 Show source
static VALUE
rb_fiddle_ptr_size_get(VALUE self)
{
    return LONG2NUM(RPTR_DATA(self)->size);
}

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

size=(size) Show source
static VALUE
rb_fiddle_ptr_size_set(VALUE self, VALUE size)
{
    RPTR_DATA(self)->size = NUM2LONG(size);
    return size;
}

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

to_i Show source
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_i
to_s → string Show source
to_s(len) → string
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.

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