require 'ffi/pointer'
module FFI
class MemoryPointer
# call-seq:
# MemoryPointer.new(num) => MemoryPointer instance of num bytes
# MemoryPointer.new(sym) => MemoryPointer instance with number
# of bytes need by FFI type sym
# MemoryPointer.new(obj) => MemoryPointer instance with number
# of obj.size bytes
# MemoryPointer.new(sym, count) => MemoryPointer instance with number
# of bytes need by length-count array
# of FFI type sym
# MemoryPointer.new(obj, count) => MemoryPointer instance with number
# of bytes need by length-count array
# of obj.size bytes
# MemoryPointer.new(arg) { |p| ... }
#
# Both forms create a MemoryPointer instance. The number of bytes to
# allocate is either specified directly or by passing an FFI type, which
# specifies the number of bytes needed for that type.
#
# The form without a block returns the MemoryPointer instance. The form
# with a block yields the MemoryPointer instance and frees the memory
# when the block returns. The value returned is the value of the block.
def self.new(type, count=nil, clear=true)
size = if type.kind_of? Fixnum
type
elsif type.kind_of? Symbol
FFI.type_size(type)
else
type.size
end
ptr = self.__allocate(size, count, clear)
ptr.type_size = size
if block_given?
begin
value = yield ptr
ensure
ptr.free
end
value
else
ptr
end
end
def self.from_string(s)
ptr = self.new(s.length + 1, 1, false)
ptr.put_string(0, s)
ptr
end
# Indicates how many bytes the type that the pointer is cast as uses.
attr_accessor :type_size
# Access the MemoryPointer like a C array, accessing the +which+ number
# element in memory. The position of the element is calculate from
# +@type_size+ and +which+. A new MemoryPointer object is returned, which
# points to the address of the element.
#
# Example:
# ptr = MemoryPointer.new(:int, 20)
# new_ptr = ptr[9]
#
# c-equiv:
# int *ptr = (int*)malloc(sizeof(int) * 20);
# int *new_ptr;
# new_ptr = &ptr[9];
#
def [](which)
raise ArgumentError, "unknown type size" unless @type_size
self + (which * @type_size)
end
end
end
MemoryPointer = FFI::MemoryPointer