класс Fiddle::Pointer
Fiddle::Pointer — это класс для работы с C-указателями
Атрибуты
Публичные методы класса
Получить базовый указатель для объекта Ruby val и вернуть его как объект Fiddle::Pointer.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 236 def self.from_native(value, ctx) self.new(value) end
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 338
def self.malloc(size, free = nil)
if block_given? and free.nil?
message = "a free function must be supplied to #{self}.malloc " +
"when it is called with a block"
raise ArgumentError, message
end
pointer = new(LibC.malloc(size), size, free)
if block_given?
begin
yield(pointer)
ensure
pointer.call_free
end
else
pointer
end
end Примеры
# 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.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 300
def initialize(addr, size = nil, free = nil)
ptr = if addr.is_a?(FFI::Pointer)
addr
elsif addr.is_a?(Integer)
FFI::Pointer.new(addr)
elsif addr.respond_to?(:to_ptr)
fiddle_ptr = addr.to_ptr
if fiddle_ptr.is_a?(Pointer)
fiddle_ptr.ffi_ptr
elsif fiddle_ptr.is_a?(FFI::AutoPointer)
addr.ffi_ptr
elsif fiddle_ptr.is_a?(FFI::Pointer)
fiddle_ptr
else
raise DLError.new("to_ptr should return a Fiddle::Pointer object, was #{fiddle_ptr.class}")
end
elsif addr.is_a?(IO)
raise NotImplementedError, "IO ptr isn't supported"
else
FFI::Pointer.new(Integer(addr))
end
@size = size ? size : ptr.size
@free = free
@ffi_ptr = ptr
@freed = false
end Исходный код
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);
}
RB_OBJ_WRITE(self, &data->wrap[0], wrap);
RB_OBJ_WRITE(self, &data->wrap[1], funcwrap);
data->ptr = p;
data->size = s;
data->free = f;
}
return Qnil;
} Создать новый указатель на address с необязательным size и freefunc.
freefunc будет вызван при сборе мусора экземпляра.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 269 def self.read(addr, len) FFI::Pointer.new(addr).read_bytes(len) end
Или считать память по адресу address длиной len и вернуть строку с этой памятью
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 224
def self.to_native(value, ctx)
if value.is_a?(Pointer)
value.ffi_ptr
elsif value.is_a?(Integer)
FFI::Pointer.new(value)
elsif value.is_a?(String)
value
end
end Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 240
def self.to_ptr(value)
if value.is_a?(String)
cptr = Pointer.malloc(value.bytesize)
cptr.ffi_ptr.put_string(0, value)
cptr
elsif value.is_a?(Array)
raise NotImplementedError, "array ptr"
elsif value.respond_to?(:to_ptr)
ptr = value.to_ptr
case ptr
when Pointer
ptr
when FFI::Pointer
Pointer.new(ptr)
else
raise DLError.new("to_ptr should return a Fiddle::Pointer object, was #{ptr.class}")
end
else
Pointer.new(value)
end
end Получить базовый указатель для объекта Ruby val и вернуть его как объект Fiddle::Pointer.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 265 def self.write(addr, bytes) FFI::Pointer.new(addr).write_bytes(bytes) end
Записать байты в str в место, на которое указывает address.
Публичные методы экземпляра
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 440 def +(delta) self.class.new(to_i + delta, @size - delta) end
Возвращает новый экземпляр указателя, который был сдвинут на n байт.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 468 def +@ ptr end
Возвращает новый экземпляр Fiddle::Pointer, который является разыменованным указателем для этого указателя.
Аналогично оператору звездочки в C.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 444 def -(delta) self.class.new(to_i - delta, @size + delta) end
Возвращает новый экземпляр указателя, который был сдвинут назад на n байт.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 472 def -@ ref end
Возвращает новый экземпляр Fiddle::Pointer, который является ссылочным указателем для этого указателя.
Аналогично оператору амперсанда в C.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 448 def <=>(other) return unless other.is_a?(Pointer) diff = self.to_i - other.to_i return 0 if diff == 0 diff > 0 ? 1 : -1 end
Возвращает -1, если меньше, 0, если равно, 1, если больше other.
Возвращает nil, если ptr не может быть сравнен с other.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 460 def ==(other) eql?(other) end
Возвращает true, если other содержит тот же указатель, иначе возвращает false.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 396
def [](index, length = nil)
if length
ffi_ptr.get_bytes(index, length)
else
ffi_ptr.get_char(index)
end
rescue FFI::NullPointerError
raise DLError.new("NULL pointer dereference")
end Возвращает целое число, хранящееся по индексу.
Если заданы start и length, будет возвращена строка, содержащая байты, начиная с start длиной length.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 277
def []=(*args, value)
if args.size == 2
if value.is_a?(Integer)
value = self.class.new(value)
end
if value.is_a?(Fiddle::Pointer)
value = value.to_str(args[1])
end
@ffi_ptr.put_bytes(args[0], value, 0, args[1])
elsif args.size == 1
if value.is_a?(Fiddle::Pointer)
value = value.to_str(args[0] + 1)
else
value = value.chr
end
@ffi_ptr.put_bytes(args[0], value, 0, 1)
end
rescue FFI::NullPointerError
raise DLError.new("NULL pointer access")
end Set значение по index на int.
Или установить память по start до length с содержимым string, памятью из dl_cptr, или памятью, на которую указывает адрес памяти addr.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 377
def call_free
return if @free.nil?
return if @freed
if @free == RUBY_FREE
LibC::FREE.call(@ffi_ptr)
else
@free.call(@ffi_ptr)
end
@freed = true
end Вызвать функцию освобождения для этого указателя. Вызов более одного раза ничего не сделает. Ничего не делает, если функция освобождения не прикреплена.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 455 def eql?(other) return unless other.is_a?(Pointer) self.to_i == other.to_i end
Возвращает true, если other содержит тот же указатель, иначе возвращает false.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 369 def free @free end
Получить функцию освобождения для этого указателя.
Возвращает новый экземпляр Fiddle::Function.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 373 def free=(free) @free = free end
Set функцию освобождения для этого указателя на function в заданном Fiddle::Function.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 388 def freed? @freed end
Возвращает, была ли вызвана функция освобождения для этого указателя.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 436
def inspect
"#<#{self.class.name} ptr=#{to_i.to_s(16)} size=#{@size} free=#{@free.inspect}>"
end Возвращает строку, отформатированную с легко читаемым представлением внутреннего состояния указателя.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 357 def null? @ffi_ptr.null? end
Возвращает true, если это нулевой указатель.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 464 def ptr Pointer.new(ffi_ptr.get_pointer(0)) end
Возвращает новый экземпляр Fiddle::Pointer, который является разыменованным указателем для этого указателя.
Аналогично оператору звездочки в C.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 476 def ref cptr = Pointer.malloc(FFI::Type::POINTER.size, RUBY_FREE) cptr.ffi_ptr.put_pointer(0, ffi_ptr) cptr end
Возвращает новый экземпляр Fiddle::Pointer, который является ссылочным указателем для этого указателя.
Аналогично оператору амперсанда в C.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 365 def size defined?(@layout) ? @layout.size : @size end
Получить размер этого указателя.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 392 def size=(size) @size = size end
Set размер этого указателя на size
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 406 def to_i ffi_ptr.to_i end
Возвращает целое значение памяти этого указателя.
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 361 def to_ptr @ffi_ptr end
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 412
def to_s(len = nil)
if len
ffi_ptr.get_string(0, len)
else
ffi_ptr.get_string(0)
end
rescue FFI::NullPointerError
raise DLError.new("NULL pointer access")
end без 0
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 422
def to_str(len = nil)
if len
ffi_ptr.read_string(len)
else
ffi_ptr.read_string(@size)
end
rescue FFI::NullPointerError
raise DLError.new("NULL pointer access")
end ptr.to_str => string ptr.to_str(len) => string
Возвращает содержимое указателя в виде строки.
При вызове без аргументов этот метод вернет содержимое с длиной size этого указателя.
При вызове с len, будет возвращена строка из len байтов.
См. to_s
Исходный код
# File ext/fiddle/lib/fiddle/ffi_backend.rb, line 432 def to_value raise NotImplementedError, "to_value isn't supported" end
Преобразовать этот указатель в объект ruby.
Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.