The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

FFI Boundary Semantics

This article is about what actually crosses the R/C boundary in Rtinycc:

The statements below are based on the implemented wrapper generator and runtime helpers.

Scalar Inputs Are Converted

Scalar inputs are converted at the boundary. For example:

So scalar arguments are not zero-copy views into R objects. They become C scalars inside the wrapper.

Vector Inputs Are Usually Borrowed

The array input types:

are passed as direct pointers into the underlying R vector storage.

That means:

This is the main zero-copy part of the FFI boundary.

cstring_array Is Rebuilt Per Call

cstring_array is different. The wrapper allocates a temporary const char ** with R_alloc() and fills it by translating each R string element.

So:

Returned Arrays Are Copied into Fresh R Vectors

Array returns are always copied into a newly allocated R vector. The wrapper uses the declared length_arg to size the R result, then memcpy() copies the returned C buffer into that vector.

If free = TRUE, the wrapper also frees the original returned buffer after the copy.

So array returns are not borrowed views into C memory.

Returned cstring Values Are Copied

For cstring returns, the wrapper creates an R string with mkString() when the returned pointer is non-NULL.

That means the resulting R value is a copy in R-managed memory, not a retained external pointer to the original C string.

Returned ptr Values Stay as Pointers

For ptr returns, the wrapper constructs an external pointer around the raw address.

That means:

The same distinction matters for globals and struct fields.

sexp Passes Through Directly

sexp is the most direct boundary mode:

This is useful when you want the R C API contract rather than the stricter FFI conversion layer.

Owned vs Borrowed Helper Pointers

At the helper level:

Use tcc_ptr_is_owned() when you need to distinguish these cases in R code.

Bitfields Are Scalar Helpers, Not Addressable Views

Bitfield helpers behave like scalar getter/setter helpers at the R boundary, but that does not make them ordinary addressable fields.

In particular:

So bitfields are intentionally excluded from the borrowed-address helper model.

Serialization Boundary

Compiled tcc_compiled objects store enough recipe information to recompile after serialize() / unserialize() or readRDS().

Raw pointers and raw tcc_state objects do not gain that behavior. After serialization they are just dead addresses or invalid states, not auto-reconstructed resources. The same applies to callback tokens, struct/union external pointers, and helper allocations from tcc_malloc() or tcc_cstring(): they do not serialize as live native resources.

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.