ffi.pointer
import ffi.pointer
ffilifts part of this module out to its own top level; each name below is shown with the path that reaches it. Anything still spelledffi.pointer.*needsimport ffi.pointer.
Addresses in native memory, and reading and writing through them.
A Pointer is an address with, optionally, the type of what it points
at. The type is what get(), set() and the field methods read and
write, and the unit add() steps by; read() and write() take a type
of their own and work on any pointer.
Memory this module allocated knows its own extent, and every access through a pointer into it is checked against that extent and against the memory having been freed. A pointer C handed back carries no extent, so only a null pointer is caught; reading past what the C library says is there is as undefined as it is in C.
Classes
Pointer
class ffi.Pointer
An address in native memory.
Pointers come from ffi.alloc() and its siblings, from functions that
return one, and from reading a pointer out of memory. A null pointer
returned from C arrives as nil instead, so if ptr is how a program
checks for one.
Memory from ffi.alloc() is freed when the last pointer into it is
collected. Keep a pointer reachable for as long as C code holds the
address.
- printable — has a
@to_string(), soechoandprint()show something useful
Constructor
ffi.Pointer()
Pointer.address()
ffi.Pointer.address() -> number|bigint
The address, as a number, or as a bigint where it is too large for a number to hold exactly.
Returns number|bigint
Pointer.is_null()
ffi.Pointer.is_null() -> bool
Whether the address is zero. A null pointer only exists as the result of
arithmetic or ffi.at(0); C returning one gives nil.
Returns bool
Pointer.type()
ffi.Pointer.type() -> Type|nil
The type of what the pointer points at, or nil for an untyped pointer
such as ffi.alloc_bytes() returns.
Returns Type|nil
Pointer.cast()
ffi.Pointer.cast(type) -> Pointer
The same address, pointing at type instead. Bounds and ownership carry
over. Pass nil for an untyped pointer.
Parameters
type(Type|nil)
Returns Pointer
Pointer.offset()
ffi.Pointer.offset(bytes) -> Pointer
The pointer bytes further on, negative for back. Keeps the type.
Parameters
bytes(number)
Returns Pointer
Pointer.add()
ffi.Pointer.add(count) -> Pointer
The pointer count elements further on, as C’s ptr + count is.
Parameters
count(number) — Negative steps back.
Returns Pointer
Raises TypeError when the pointer has no element type, or its
element type has no size.
Pointer.size()
ffi.Pointer.size() -> number|nil
How many bytes are known to be addressable from here to the end of the
block, or nil when the extent is unknown, as it is for any pointer C
handed back.
Returns number|nil
Pointer.read()
ffi.Pointer.read(type, offset) -> any
Reads a value of type at offset bytes from the pointer.
var header = ffi.alloc_bytes(16)
var magic = header.read(ffi.uint32)
var length = header.read(ffi.uint64, 8)
Parameters
type(Type)offset(number|nil) — Defaults to 0.
Returns any
Raises PointerError when the pointer is null, the memory is freed,
or the read runs outside a known block.
Pointer.write()
ffi.Pointer.write(type, value, offset)
Writes value as type at offset bytes from the pointer.
Nothing is written when the value does not convert, so a failed write never leaves half a value behind. Writing a record or array as a whole replaces every member; members the value leaves out keep what they held.
Parameters
type(Type)value(any)offset(number|nil) — Defaults to 0.
Raises PointerError for the reasons read() does.
Raises TypeError when value cannot be stored as type.
Raises RangeError when a number does not fit type.
Pointer.get()
ffi.Pointer.get(index) -> any
Reads element index of the pointer’s type, as C’s ptr[index].
Parameters
index(number|nil) — Defaults to 0.
Returns any
Raises TypeError when the pointer has no element type.
Raises PointerError for the reasons read() does.
Pointer.set()
ffi.Pointer.set(index, value)
Writes element index of the pointer’s type, as C’s ptr[index] = value.
Parameters
index(number)value(any)
Raises TypeError when the pointer has no element type or the value
does not convert.
Raises PointerError for the reasons read() does.
Pointer.get_field()
ffi.Pointer.get_field(name) -> any
Reads one member of the struct or union the pointer points at, as C’s
ptr->name. Bitfields read like any other member.
Parameters
name(string)
Returns any
Raises TypeError when the pointer does not point at a record.
Raises ValueError when the record has no such member.
Pointer.set_field()
ffi.Pointer.set_field(name, value)
Writes one member of the struct or union the pointer points at, as C’s
ptr->name = value, leaving the other members alone.
Parameters
name(string)value(any)
Raises TypeError when the pointer does not point at a record, or
the value does not convert.
Raises ValueError when the record has no such member.
Raises RangeError when a number does not fit, including a
bitfield’s width.
Pointer.field()
ffi.Pointer.field(name) -> Pointer
A pointer to one member, typed as the member, as C’s &ptr->name.
Reaching into nested records is a chain of these.
An array member gives a pointer to its first element instead, typed as the element, as the member itself decays to in C. That is how a flexible array member’s elements are reached.
Parameters
name(string)
Returns Pointer
Raises TypeError for a bitfield, which has no address.
Pointer.read_string()
ffi.Pointer.read_string(length, encoding, offset) -> string
Reads text.
With a length, exactly that many code units; without one, up to the
first zero code unit, which must lie within the block when the block’s
extent is known.
Parameters
length(number|nil) — In code units, not bytes.encoding(string|nil) —'utf-8'(the default),'utf-16','utf-32', or'wide'forwchar_t, which is UTF-16 on Windows and UTF-32 elsewhere.offset(number|nil) — In bytes. Defaults to 0.
Returns string
Raises ValueError when the text is not valid in its encoding.
Raises PointerError when there is no terminator inside a known
block.
Pointer.write_string()
ffi.Pointer.write_string(text, encoding, offset) -> number
Writes text and a terminating zero, returning the bytes written.
Parameters
text(string)encoding(string|nil) — As forread_string().offset(number|nil) — In bytes. Defaults to 0.
Returns number
Raises PointerError when the text and terminator do not fit a
known block.
Pointer.read_bytes()
ffi.Pointer.read_bytes(length, offset) -> bytes
Copies length bytes out.
Parameters
length(number)offset(number|nil) — Defaults to 0.
Returns bytes
Pointer.write_bytes()
ffi.Pointer.write_bytes(data, offset) -> number
Copies data in, returning how many bytes were written.
Parameters
data(bytes)offset(number|nil) — Defaults to 0.
Returns number
Pointer.to_list()
ffi.Pointer.to_list(count) -> list
Reads count elements of the pointer’s type into a list.
Parameters
count(number)
Returns list
Pointer.copy_from()
ffi.Pointer.copy_from(source, length)
Copies length bytes from source, a pointer or bytes, to here. The
two ranges may overlap.
Parameters
source(Pointer|bytes)length(number)
Pointer.fill()
ffi.Pointer.fill(byte, length)
Sets length bytes to byte.
Parameters
byte(number) — 0 to 255.length(number)
Pointer.compare()
ffi.Pointer.compare(other, length) -> number
Compares length bytes here with length bytes at other, as memcmp
does: -1, 0 or 1.
Parameters
other(Pointer)length(number)
Returns number
Pointer.own()
ffi.Pointer.own(destructor)
Takes ownership of memory C allocated, so it is released when the pointer is collected.
destructor is the C function that releases it, taking the address as
its one argument. Leave it out for memory from the C allocator, which
free releases. Pointers derived from this one afterwards share the
ownership.
A destructor run by the collector cannot call back into Zuri: any
callback it calls returns zero to C, or its error_value. free() runs
the destructor with callbacks working as usual.
var text = c.strdup('hello').own()
var db = sqlite.open_handle(path).own(sqlite.sqlite3_close)
Parameters
destructor(function|nil) — A foreign function of one pointer.
Returns — self
Raises PointerError when the pointer is null or already owned.
Raises TypeError when the destructor is not a foreign function of
one pointer.
Pointer.free()
ffi.Pointer.free()
Releases owned memory now rather than when it is collected: memory from
ffi.alloc() or ffi.malloc(), or taken over with own(). Every
pointer into it refuses access from then on.
Raises PointerError when the pointer does not own its memory, does
not point at the start of it, or it has already been freed.
Pointer.is_freed()
ffi.Pointer.is_freed() -> bool
Whether the memory this pointer owns has been freed.
Returns bool
Pointer.is_owned()
ffi.Pointer.is_owned() -> bool
Whether this pointer owns its memory: it came from ffi.alloc() or
ffi.malloc(), or own() was called on it or a pointer it came from.
Returns bool
Pointer.equals()
ffi.Pointer.equals(other) -> bool
Whether other is a pointer to the same address.
Parameters
other(any)
Returns bool
Pointer.to_string()
ffi.Pointer.to_string()
2026, Richard Ore and Zuri contributors