--- title: "FFI Helper APIs" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{FFI Helper APIs} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) tcc_cstring <- Rtinycc::tcc_cstring tcc_data_ptr <- Rtinycc::tcc_data_ptr tcc_free <- Rtinycc::tcc_free tcc_malloc <- Rtinycc::tcc_malloc tcc_null_ptr <- Rtinycc::tcc_null_ptr tcc_ptr_addr <- Rtinycc::tcc_ptr_addr tcc_ptr_is_null <- Rtinycc::tcc_ptr_is_null tcc_ptr_is_owned <- Rtinycc::tcc_ptr_is_owned tcc_ptr_set <- Rtinycc::tcc_ptr_set tcc_read_bytes <- Rtinycc::tcc_read_bytes tcc_read_cstring <- Rtinycc::tcc_read_cstring tcc_read_f64 <- Rtinycc::tcc_read_f64 tcc_read_i32 <- Rtinycc::tcc_read_i32 tcc_write_bytes <- Rtinycc::tcc_write_bytes tcc_write_f64 <- Rtinycc::tcc_write_f64 tcc_write_i32 <- Rtinycc::tcc_write_i32 ``` The helper APIs are the low-level tools you use when a binding needs explicit memory management, pointer inspection, or typed reads and writes. ## Allocation and Ownership The owned-memory helpers are `tcc_malloc()` and `tcc_cstring()`. ```{r} buf <- tcc_malloc(16) str_ptr <- tcc_cstring("hello") tcc_ptr_is_owned(buf) tcc_ptr_is_owned(str_ptr) ``` Both return owned external pointers. They can be freed explicitly with `tcc_free()` and also carry finalizers. ```{r} tcc_free(buf) tcc_free(str_ptr) ``` ## Reading and Writing Raw Bytes ```{r} buf <- tcc_malloc(8) tcc_write_bytes(buf, as.raw(1:8)) tcc_read_bytes(buf, 8) tcc_free(buf) ``` ## Typed Reads and Writes The helper layer also exposes typed accessors for primitive values at byte offsets. ```{r} buf <- tcc_malloc(16) tcc_write_i32(buf, 0L, 42L) tcc_write_f64(buf, 8L, 3.5) tcc_read_i32(buf, offset = 0L) tcc_read_f64(buf, offset = 8L) tcc_free(buf) ``` These helpers are useful for manual struct-like layouts, output buffers, or pointer-heavy APIs that do not map cleanly onto ordinary R vectors. ## Pointer-to-Pointer Helpers Some C APIs fill outputs through `T **` or `void **`. `Rtinycc` exposes a small set of helpers for that pattern. ```{r} ptr_size <- if (!is.null(.Machine$sizeof.pointer)) .Machine$sizeof.pointer else 8L ptr_ref <- tcc_malloc(ptr_size) target <- tcc_malloc(4) tcc_ptr_set(ptr_ref, target) tcc_ptr_addr(tcc_data_ptr(ptr_ref)) tcc_ptr_addr(target) tcc_ptr_set(ptr_ref, tcc_null_ptr()) tcc_ptr_is_null(tcc_data_ptr(ptr_ref)) tcc_free(target) tcc_free(ptr_ref) ``` `tcc_data_ptr()` returns a borrowed pointer view. It is not an owned allocation. ## C String Helpers ```{r} str_ptr <- tcc_cstring("Hello, world") tcc_read_cstring(str_ptr) tcc_read_cstring(str_ptr, max_bytes = 5) tcc_free(str_ptr) ``` This helper is the safe way to allocate a C-owned NUL-terminated string when the callee expects a mutable or longer-lived `char *`.