Spec-Zone.ru › Ruby 3.1

класс 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 Показать исходный код
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 or 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] → an_integer Показать исходный код
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;
}

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

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

ptr[index] = int → int Показать исходный код
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 Показать исходный код
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 Показать исходный код
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_int()

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

Псевдоним для: to_i
to_s → string Показать исходный код
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 → string Показать исходный код
to_str(len) → string
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

END_OF_DOCUMENT_MARKER
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