knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) tcc_bind <- Rtinycc::tcc_bind tcc_callback <- Rtinycc::tcc_callback tcc_callback_async_drain <- Rtinycc::tcc_callback_async_drain tcc_callback_close <- Rtinycc::tcc_callback_close tcc_callback_ptr <- Rtinycc::tcc_callback_ptr tcc_compile <- Rtinycc::tcc_compile tcc_ffi <- Rtinycc::tcc_ffi tcc_source <- Rtinycc::tcc_source tcc_struct <- Rtinycc::tcc_struct
This vignette covers two patterns that come up quickly in real bindings:
Struct helpers are generated from a declarative description. In the example
below, Rtinycc creates allocation, field getter, field setter, and free
helpers for a simple struct point.
ffi_struct <- tcc_ffi() |> tcc_source( " struct point { double x; double y; }; double point_norm2(struct point* p) { return p->x * p->x + p->y * p->y; } " ) |> tcc_struct("point", accessors = c(x = "f64", y = "f64")) |> tcc_bind( point_norm2 = list(args = list("ptr"), returns = "f64") ) |> tcc_compile() pt <- ffi_struct$struct_point_new() pt <- ffi_struct$struct_point_set_x(pt, 3) pt <- ffi_struct$struct_point_set_y(pt, 4) ffi_struct$point_norm2(pt) ffi_struct$struct_point_free(pt)
This keeps the C layout explicit while still giving you a usable R-facing surface.
Named nested struct fields can also be modeled directly with struct:<name>.
Those getters return borrowed nested views and setters copy bytes from a source
struct object of the matching nested type.
Callbacks let compiled C code invoke an R function through a generated trampoline. The callback object and the callback pointer play different roles:
tcc_callback object owns the registered R functiontcc_callback_ptr() returns the user-data handle that C trampolines expectcb <- tcc_callback( function(x) x * 2, signature = "double (*)(double)" ) cb_ptr <- tcc_callback_ptr(cb) ffi_cb <- tcc_ffi() |> tcc_source( " double apply_cb(double (*cb)(void* ctx, double), void* ctx, double x) { return cb(ctx, x); } " ) |> tcc_bind( apply_cb = list( args = list("callback:double(double)", "ptr", "f64"), returns = "f64" ) ) |> tcc_compile() ffi_cb$apply_cb(cb, cb_ptr, 5) tcc_callback_close(cb)
tcc_callback_close() is recommended when you want deterministic invalidation
and prompt release of the preserved R function. If you simply drop all
references, finalizers will still clean up the callback eventually.
callback_async:<signature> is the safe path for worker-thread callbacks, but
its contract is narrower than the synchronous trampoline path:
i64, u32, and u64 async arguments and returns are marshalled through
R numeric (double), so only exact integer values up to 2^53 are exacttcc_callback_async_drain() explicitlyThe callback contract is deliberately explicit:
That explicitness is part of what keeps Rtinycc predictable as a systems
interface rather than a partial compiler front-end.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.