JARVIGManual

Memory, strings, and arrays

Ownership at the ABI is explicit. If a function does not say, it is wrong.

Rules

KindMeaning
Caller-owned inputThe pointer is valid only for the call. The engine copies what it needs to keep.
Caller-provided outputThe caller passes a buffer and a capacity. The engine writes into it and reports the count.
Engine-owned viewThe pointer is valid until the next mutating call on that object, or until a documented lifetime ends. The caller copies it if it must keep the bytes.
Explicit releaseThe engine allocated. The caller later calls the matching jarvig_*_release.

The caller never frees memory the engine allocated. The engine never frees memory the plugin allocated. If ownership must move, the release function is in the same module that allocated, and the header names it.

Allocators are not mixed. A plugin that needs engine memory asks the engine. It does not pass a function pointer to a different CRT heap and expect the engine to call it, unless a future allocator ticket defines that on purpose.

Strings

UTF-8. The length is the authority. The bytes are not required to be null-terminated. No std::string. No Rust String. No wchar_t as the canonical encoding.

JarvigString
    const char *data
    uint32_t    length

A convenience that also writes a trailing NUL into a caller buffer is allowed. The length still does not include that NUL, so an embedded NUL is data, not a terminator.

Arrays

JarvigBytes
    const void *data
    uint32_t    length

JarvigSlice
    const void *data
    uint32_t    count
    uint32_t    stride

stride is the byte step between elements. It lets a newer struct be read by an older caller only when the versioning rule for that struct allows it. Do not pass a Vec<T> or a C++ vector across the boundary. The SDK wrapper may build one on its own side after the call returns.