The small memory chores every cdylib binding repeats: NULL checks, reading a
char* back into a String, pushing bytes/strings down as MemorySegments,
and copying an owned buffer out.
Nothing here knows about a particular library — it is the boring half of an
FFM binding, factored out so clj-ruff, clj-fff and clj-imaging stop
carrying three copies of it.
All allocation takes an explicit Arena: the caller decides the lifetime
(Arena/ofConfined in a with-open for a call's scratch, Arena/ofAuto for
process-lifetime handles).
The small memory chores every cdylib binding repeats: NULL checks, reading a `char*` back into a String, pushing bytes/strings down as `MemorySegment`s, and copying an owned buffer out. Nothing here knows about a particular library — it is the boring half of an FFM binding, factored out so `clj-ruff`, `clj-fff` and `clj-imaging` stop carrying three copies of it. All allocation takes an explicit `Arena`: the caller decides the lifetime (`Arena/ofConfined` in a `with-open` for a call's scratch, `Arena/ofAuto` for process-lifetime handles).
(->bytes arena ba)Copy a byte array into arena as a raw (NOT NUL-terminated) segment.
NULL for nil; a zero-length input still yields a valid 1-byte segment so the
pointer is never NULL when a length of 0 is also passed.
Copy a byte array into `arena` as a raw (NOT NUL-terminated) segment. NULL for nil; a zero-length input still yields a valid 1-byte segment so the pointer is never NULL when a length of 0 is also passed.
(->c-string arena s)Allocate a NUL-terminated UTF-8 copy of s in arena. NULL for nil.
Allocate a NUL-terminated UTF-8 copy of `s` in `arena`. NULL for nil.
(->strings arena strs)Allocate a char*[] of strs in arena (for the common (ptr, len) pair).
NULL when strs is empty or nil.
Allocate a `char*[]` of `strs` in `arena` (for the common `(ptr, len)` pair). NULL when `strs` is empty or nil.
(bytes<- seg len)Copy len bytes out of seg into a fresh byte array. nil for NULL.
Copy `len` bytes out of `seg` into a fresh byte array. nil for NULL.
(c-string seg)Read a NUL-terminated UTF-8 string from seg WITHOUT freeing it. nil for NULL.
The segment is reinterpreted with an unbounded size first: a pointer that came back from a downcall is zero-length, so reading it directly throws.
Read a NUL-terminated UTF-8 string from `seg` WITHOUT freeing it. nil for NULL. The segment is reinterpreted with an unbounded size first: a pointer that came back from a downcall is zero-length, so reading it directly throws.
(confined f)Run (f arena) in a fresh confined arena, freeing everything on exit.
Anything the callee must keep has to be copied out before returning.
Run `(f arena)` in a fresh confined arena, freeing everything on exit. Anything the callee must keep has to be copied out before returning.
(null? seg)True for nil and for a segment whose address is 0.
True for nil and for a segment whose address is 0.
(take-string! free! seg)Read an OWNED char* result and hand it back to the library. nil for NULL.
free! is a 1-arg fn (usually #(nr/invoke handles :free-string %)) that
calls the library's own deallocator — freeing a Rust CString with anything
else corrupts the heap.
Read an OWNED `char*` result and hand it back to the library. nil for NULL. `free!` is a 1-arg fn (usually `#(nr/invoke handles :free-string %)`) that calls the library's own deallocator — freeing a Rust `CString` with anything else corrupts the heap.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |