Class: Fiddle::Pointer
- Inherits:
-
Object
- Object
- Fiddle::Pointer
- Extended by:
- FFI::DataConverter
- Defined in:
- ext/fiddle/pointer.c,
lib/fiddle/ffi_backend.rb,
ext/fiddle/pointer.c
Overview
Fiddle::Pointer is a class to handle C pointers
Direct Known Subclasses
Defined Under Namespace
Modules: LibC
Instance Attribute Summary collapse
-
#ffi_ptr ⇒ Object
readonly
Returns the value of attribute ffi_ptr.
Class Method Summary collapse
-
.[](val) ⇒ Object
Get the underlying pointer for ruby object
val
and return it as a Fiddle::Pointer object. - .from_native(value, ctx) ⇒ Object
-
.malloc(argv[], klass) ⇒ Object
Examples.
-
.Fiddle::Pointer.read(address, len) ⇒ String
Or read the memory at address
address
with lengthlen
and return a string with that memory. - .to_native(value, ctx) ⇒ Object
-
.to_ptr(val) ⇒ Object
Get the underlying pointer for ruby object
val
and return it as a Fiddle::Pointer object. -
.Fiddle::Pointer.write(address, str) ⇒ Object
Write bytes in
str
to the location pointed to byaddress
.
Instance Method Summary collapse
-
#+(n) ⇒ Object
Returns a new pointer instance that has been advanced
n
bytes. -
#ptr ⇒ Object
Returns a new Fiddle::Pointer instance that is a dereferenced pointer for this pointer.
-
#-(n) ⇒ Object
Returns a new pointer instance that has been moved back
n
bytes. -
#ref ⇒ Object
Returns a new Fiddle::Pointer instance that is a reference pointer for this pointer.
-
#<=>(other) ⇒ -1, ...
Returns -1 if less than, 0 if equal to, 1 if greater than
other
. -
#==(other) ⇒ Object
Returns true if
other
wraps the same pointer, otherwise returns false. -
#[](argv[], self) ⇒ Object
Returns integer stored at index.
-
#[]=(argv[], self) ⇒ Object
Set the value at
index
toint
. -
#call_free ⇒ nil
Call the free function for this pointer.
-
#eql?(other) ⇒ Object
Returns true if
other
wraps the same pointer, otherwise returns false. -
#free ⇒ Fiddle::Function
Get the free function for this pointer.
-
#free=(function) ⇒ Object
Set the free function for this pointer to
function
in the given Fiddle::Function. -
#freed? ⇒ Boolean
Returns if the free function for this pointer has been called.
-
#initialize(argv[], self) ⇒ Object
constructor
Create a new pointer to
address
with an optionalsize
andfreefunc
. -
#inspect ⇒ Object
Returns a string formatted with an easily readable representation of the internal state of the pointer.
-
#null? ⇒ Boolean
Returns
true
if this is a null pointer. -
#ptr ⇒ Object
Returns a new Fiddle::Pointer instance that is a dereferenced pointer for this pointer.
-
#ref ⇒ Object
Returns a new Fiddle::Pointer instance that is a reference pointer for this pointer.
-
#size ⇒ Object
Get the size of this pointer.
-
#size=(size) ⇒ Object
Set the size of this pointer to
size
. -
#to_i ⇒ Object
(also: #to_int)
Returns the integer memory location of this pointer.
- #to_ptr ⇒ Object
-
#to_s(argv[], self) ⇒ Object
Returns the pointer contents as a string.
-
#to_str(argv[], self) ⇒ Object
Returns the pointer contents as a string.
-
#to_value ⇒ Object
Cast this pointer to a ruby object.
Constructor Details
#Fiddle::Pointer.new(address) ⇒ Object #new(address, size) ⇒ Object #new(address, size, freefunc) ⇒ Object
Create a new pointer to address
with an optional size
and freefunc
.
freefunc
will be called when the instance is garbage collected.
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'ext/fiddle/pointer.c', line 216 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 |
Instance Attribute Details
#ffi_ptr ⇒ Object (readonly)
Returns the value of attribute ffi_ptr.
220 221 222 |
# File 'lib/fiddle/ffi_backend.rb', line 220 def ffi_ptr @ffi_ptr end |
Class Method Details
.Fiddle::Pointer ⇒ Object .to_ptr(val) ⇒ Object
Get the underlying pointer for ruby object val
and return it as a Fiddle::Pointer object.
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 |
# File 'ext/fiddle/pointer.c', line 772 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 |
.from_native(value, ctx) ⇒ Object
236 237 238 |
# File 'lib/fiddle/ffi_backend.rb', line 236 def self.from_native(value, ctx) self.new(value) end |
.Fiddle::Pointer.malloc(size, freefunc = nil) ⇒ Object .Fiddle::Pointer.malloc(size, freefunc) {|pointer| ... } ⇒ Object
Examples
# 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)
...
Allocate size
bytes of memory and associate it with an optional freefunc
.
If a block is supplied, the pointer will be yielded to the block instead of being returned, and the return value of the block will be returned. A freefunc
must be supplied if a block is.
If a freefunc
is supplied it will be called once, when the pointer is garbage collected or when the block is left if a block is supplied or when the user calls call_free
, whichever happens first. freefunc
must be an address pointing to a function or an instance of Fiddle::Function
.
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'ext/fiddle/pointer.c', line 301 def self.malloc(size, free = nil) if block_given? and free.nil? = "a free function must be supplied to #{self}.malloc " + "when it is called with a block" raise ArgumentError, end pointer = new(LibC.malloc(size), size, free) if block_given? begin yield(pointer) ensure pointer.call_free end else pointer end end |
.Fiddle::Pointer.read(address, len) ⇒ String
Or read the memory at address address
with length len
and return a string with that memory
815 816 817 |
# File 'ext/fiddle/pointer.c', line 815 def self.read(addr, len) FFI::Pointer.new(addr).read_bytes(len) end |
.to_native(value, ctx) ⇒ Object
224 225 226 227 228 229 230 231 232 233 234 |
# File '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 |
.Fiddle::Pointer ⇒ Object .to_ptr(val) ⇒ Object
Get the underlying pointer for ruby object val
and return it as a Fiddle::Pointer object.
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 |
# File 'ext/fiddle/pointer.c', line 772 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 |
.Fiddle::Pointer.write(address, str) ⇒ Object
Write bytes in str
to the location pointed to by address
.
827 828 829 |
# File 'ext/fiddle/pointer.c', line 827 def self.write(addr, bytes) FFI::Pointer.new(addr).write_bytes(bytes) end |
Instance Method Details
#+(n) ⇒ Object
Returns a new pointer instance that has been advanced n
bytes.
626 627 628 |
# File 'ext/fiddle/pointer.c', line 626 def +(delta) self.class.new(to_i + delta, @size - delta) end |
#ptr ⇒ Object
Returns a new Fiddle::Pointer instance that is a dereferenced pointer for this pointer.
Analogous to the star operator in C.
369 370 371 |
# File 'ext/fiddle/pointer.c', line 369 def +@ ptr end |
#-(n) ⇒ Object
Returns a new pointer instance that has been moved back n
bytes.
644 645 646 |
# File 'ext/fiddle/pointer.c', line 644 def -(delta) self.class.new(to_i - delta, @size + delta) end |
#ref ⇒ Object
Returns a new Fiddle::Pointer instance that is a reference pointer for this pointer.
Analogous to the ampersand operator in C.
386 387 388 |
# File 'ext/fiddle/pointer.c', line 386 def -@ ref end |
#<=>(other) ⇒ -1, ...
Returns -1 if less than, 0 if equal to, 1 if greater than other
.
Returns nil if ptr
cannot be compared to other
.
605 606 607 608 609 610 |
# File 'ext/fiddle/pointer.c', line 605 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 |
#==(other) ⇒ Boolean #eql?(other) ⇒ Boolean
Returns true if other
wraps the same pointer, otherwise returns false.
584 585 586 |
# File 'ext/fiddle/pointer.c', line 584 def ==(other) eql?(other) end |
#[](index) ⇒ Integer #[](start, length) ⇒ String
Returns integer stored at index.
If start and length are given, a string containing the bytes from start of length will be returned.
666 667 668 669 670 671 672 673 674 |
# File 'ext/fiddle/pointer.c', line 666 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 |
#[]=(index) ⇒ Integer #[]=(start, length) ⇒ String
Set the value at index
to int
.
Or, set the memory at start
until length
with the contents of string
, the memory from dl_cptr
, or the memory pointed at by the memory address addr
.
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 |
# File 'ext/fiddle/pointer.c', line 703 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 |
#call_free ⇒ nil
Call the free function for this pointer. Calling more than once will do nothing. Does nothing if there is no free function attached.
462 463 464 465 466 467 468 469 470 471 |
# File 'ext/fiddle/pointer.c', line 462 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 |
#==(other) ⇒ Boolean #eql?(other) ⇒ Boolean
Returns true if other
wraps the same pointer, otherwise returns false.
584 585 586 587 |
# File 'ext/fiddle/pointer.c', line 584 def eql?(other) return unless other.is_a?(Pointer) self.to_i == other.to_i end |
#free ⇒ Fiddle::Function
Get the free function for this pointer.
Returns a new instance of Fiddle::Function.
See Fiddle::Function.new
435 436 437 |
# File 'ext/fiddle/pointer.c', line 435 def free @free end |
#free=(function) ⇒ Object
Set the free function for this pointer to function
in the given Fiddle::Function.
415 416 417 |
# File 'ext/fiddle/pointer.c', line 415 def free=(free) @free = free end |
#freed? ⇒ Boolean
Returns if the free function for this pointer has been called.
476 477 478 |
# File 'ext/fiddle/pointer.c', line 476 def freed? @freed end |
#inspect ⇒ Object
Returns a string formatted with an easily readable representation of the internal state of the pointer.
566 567 568 |
# File 'ext/fiddle/pointer.c', line 566 def inspect "#<#{self.class.name} ptr=#{to_i.to_s(16)} size=#{@size} free=#{@free.inspect}>" end |
#null? ⇒ Boolean
Returns true
if this is a null pointer.
400 401 402 |
# File 'ext/fiddle/pointer.c', line 400 def null? @ffi_ptr.null? end |
#ptr ⇒ Object
Returns a new Fiddle::Pointer instance that is a dereferenced pointer for this pointer.
Analogous to the star operator in C.
369 370 371 |
# File 'ext/fiddle/pointer.c', line 369 def ptr Pointer.new(ffi_ptr.get_pointer(0)) end |
#ref ⇒ Object
Returns a new Fiddle::Pointer instance that is a reference pointer for this pointer.
Analogous to the ampersand operator in C.
386 387 388 389 390 |
# File 'ext/fiddle/pointer.c', line 386 def ref cptr = Pointer.malloc(FFI::Type::POINTER.size, RUBY_FREE) cptr.ffi_ptr.put_pointer(0, ffi_ptr) cptr end |
#size ⇒ Object
Get the size of this pointer.
758 759 760 |
# File 'ext/fiddle/pointer.c', line 758 def size defined?(@layout) ? @layout.size : @size end |
#size=(size) ⇒ Object
Set the size of this pointer to size
746 747 748 |
# File 'ext/fiddle/pointer.c', line 746 def size=(size) @size = size end |
#to_i ⇒ Object Also known as: to_int
Returns the integer memory location of this pointer.
339 340 341 |
# File 'ext/fiddle/pointer.c', line 339 def to_i ffi_ptr.to_i end |
#to_ptr ⇒ Object
361 362 363 |
# File 'lib/fiddle/ffi_backend.rb', line 361 def to_ptr @ffi_ptr end |
#to_s ⇒ String #to_s(len) ⇒ String
Returns the pointer contents as a string.
When called with no arguments, this method will return the contents until the first NULL byte.
When called with len
, a string of len
bytes will be returned.
See to_str
412 413 414 415 416 417 418 419 420 |
# File '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 |
#to_str ⇒ String #to_str(len) ⇒ String
Returns the pointer contents as a string.
When called with no arguments, this method will return the contents with the length of this pointer’s size
.
When called with len
, a string of len
bytes will be returned.
See to_s
537 538 539 540 541 542 543 544 545 |
# File 'ext/fiddle/pointer.c', line 537 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 |
#to_value ⇒ Object
Cast this pointer to a ruby object.
353 354 355 |
# File 'ext/fiddle/pointer.c', line 353 def to_value raise NotImplementedError, "to_value isn't supported" end |