Expand description
miniextendr-api: core runtime for Rust <-> R interop.
This crate provides the FFI surface, safety wrappers, and macro re-exports used by most miniextendr users. It is the primary dependency for building Rust-powered R packages and exposing Rust types to R.
At a glance:
- FFI bindings + checked wrappers for R’s C API (
ffi,r_ffi_checked). - Conversions between Rust and R types (
IntoR,TryFromSexp,Coerce). - ALTREP traits, registration helpers, and iterator-backed ALTREP data types.
- Wrapper generation from Rust signatures (
#[miniextendr], automatic registration via linkme). - Worker-thread pattern for panic isolation and
Dropsafety (worker). - Class system support (S3, S4, S7, R6, env-style impl blocks).
- Cross-package trait ABI for type-erased dispatch (
trait_abi).
Most users should depend on this crate directly. For embedding R in
standalone binaries or integration tests, see miniextendr-engine.
§Quick start
use miniextendr_api::miniextendr;
#[miniextendr]
fn add(a: i32, b: i32) -> i32 {
a + b
}That’s it — #[miniextendr] handles everything. Items self-register
at link time; miniextendr_init! generates the R_init_* function
that calls package_init() to register all routines with R.
Wrapper R code is produced from Rust doc comments (roxygen tags are
extracted) by the cdylib-based wrapper generator and committed into
R/miniextendr_wrappers.R so CRAN builds do not require codegen.
§GC protection and ownership
R’s garbage collector can reclaim any SEXP that isn’t protected. miniextendr provides three complementary protection mechanisms:
| Strategy | Module | Lifetime | Release Order | Use Case |
|---|---|---|---|---|
| PROTECT stack | gc_protect | Within .Call | LIFO (stack) | Temporary allocations |
| Preserve list | preserve | Across .Calls | Any order | Long-lived R objects |
| R ownership | ExternalPtr | Until R GCs | R decides | Rust data owned by R |
Quick guide:
Temporary allocations during computation -> ProtectScope
unsafe fn compute(x: SEXP) -> SEXP {
let scope = ProtectScope::new();
let temp = scope.protect(Rf_allocVector(REALSXP, 100));
// ... work with temp ...
result.into_raw()
} // UNPROTECT(n) called automaticallyR objects surviving across .Calls -> preserve
// In RAllocator or similar long-lived context
let cell = unsafe { preserve::insert(backing_vec) };
// ... use across multiple .Calls ...
unsafe { preserve::release(cell) };Rust data owned by R -> ExternalPtr
#[miniextendr]
fn create_model() -> ExternalPtr<MyModel> {
ExternalPtr::new(MyModel::new())
} // R owns it; Drop runs when R GCsNote: ALTREP trait methods receive raw SEXP pointers from R’s runtime. These are safe to dereference because R guarantees valid SEXPs in ALTREP callbacks.
§Threading and safety
R uses longjmp for errors, which can bypass Rust destructors. The default
pattern is to run Rust logic on a worker thread and marshal R API calls back
to the main R thread via with_r_thread. Most FFI wrappers are
main-thread routed via #[r_ffi_checked]. Use unchecked variants only when
you have arranged a safe context.
With the nonapi feature, miniextendr can disable R’s stack checking to allow
calls from other threads. R is still not thread-safe; serialize all R API use.
§Feature Flags
§Core Features
| Feature | Description |
|---|---|
nonapi | Non-API R symbols (stack controls, mutable DATAPTR). May break with R updates. |
rayon | Parallel iterators via Rayon. Adds RParallelIterator, RParallelExtend. |
connections | Experimental R connection framework. Unstable R API. |
indicatif | Progress bars via R console. Requires nonapi. |
vctrs | vctrs class construction (new_vctr, new_rcrd, new_list_of) and #[derive(Vctrs)]. |
worker-thread | Worker thread for panic isolation and Drop safety. Without it, stubs run inline. |
§Type Conversions (Scalars & Vectors)
| Feature | Rust Type | R Type | Notes |
|---|---|---|---|
either | Either<L, R> | Tries L then R | Union-like dispatch |
uuid | Uuid, Vec<Uuid> | character | UUID ↔ string |
regex | Regex | character(1) | Compiles pattern from R |
url | Url, Vec<Url> | character | Validated URLs |
time | OffsetDateTime, Date | POSIXct, Date | Date/time conversions |
ordered-float | OrderedFloat<f64> | numeric | NaN-orderable floats |
num-bigint | BigInt, BigUint | character | Arbitrary precision via strings |
rust_decimal | Decimal | character | Fixed-point decimals |
num-complex | Complex<f64> | complex | Native R complex support |
indexmap | IndexMap<String, T> | named list | Preserves insertion order |
bitflags | RFlags<T> | integer | Bitflags ↔ integer |
bitvec | RBitVec | logical | Bit vectors ↔ logical |
tinyvec | TinyVec<[T; N]>, ArrayVec<[T; N]> | vectors | Small-vector optimization |
§Matrix & Array Libraries
| Feature | Types | Conversions |
|---|---|---|
ndarray | Array1–Array6, ArrayD, views | R vectors/matrices ↔ ndarray |
nalgebra | DVector, DMatrix | R vectors/matrices ↔ nalgebra |
§Serialization
| Feature | Traits/Modules | Description |
|---|---|---|
serde | RSerializeNative, RDeserializeNative | Direct Rust ↔ R native serialization |
serde_json | RSerialize, RDeserialize | JSON string serialization (includes serde) |
borsh | Borsh<T> | Binary serialization ↔ raw vectors via Borsh |
§Adapter Traits (Generic Operations)
| Feature | Traits | Use Case |
|---|---|---|
num-traits | RNum, RSigned, RFloat | Generic numeric operations |
bytes | RBuf, RBufMut | Byte buffer operations |
§Text & Data Processing
| Feature | Types/Functions | Description |
|---|---|---|
aho-corasick | AhoCorasick, aho_compile | Fast multi-pattern string search |
toml | TomlValue, toml_from_str | TOML parsing and serialization |
tabled | table_to_string | ASCII/Unicode table formatting |
sha2 | sha256_str, sha512_bytes | Cryptographic hashing |
§Random Number Generation
| Feature | Types | Description |
|---|---|---|
rand | RRng, RDistributions | Wraps R’s RNG with rand traits |
rand_distr | Re-exports rand_distr | Additional distributions (Normal, Exp, etc.) |
§Binary Data
| Feature | Types | Description |
|---|---|---|
raw_conversions | Raw<T>, RawSlice<T> | POD types ↔ raw vectors via bytemuck |
§Project-wide Defaults (mutually exclusive where noted)
| Feature | Description |
|---|---|
default-r6 | Default class system: R6 (mutually exclusive with default-s7) |
default-s7 | Default class system: S7 (mutually exclusive with default-r6) |
default-worker | Default to worker thread dispatch (implies worker-thread) |
default-strict | Default to strict mode for lossy integer conversions |
default-coerce | Default to coerce mode for type conversions |
§Development / Diagnostics
| Feature | Description |
|---|---|
doc-lint | Warn on roxygen doc comment mismatches (enabled by default) |
macro-coverage | Expose macro coverage test module for cargo expand auditing |
debug-preserve | Enable preserve::count() diagnostic helpers (tests/benchmarks only) |
growth-debug | Track and report collection growth events (zero-cost when off) |
refcount-fast-hash | Use ahash for refcount arenas (enabled by default, not DOS-resistant) |
Re-exports§
pub use altrep_data::AltComplexData;pub use altrep_data::AltIntegerData;pub use altrep_data::AltListData;pub use altrep_data::AltLogicalData;pub use altrep_data::AltRawData;pub use altrep_data::AltRealData;pub use altrep_data::AltStringData;pub use altrep_data::AltrepDataptr;pub use altrep_data::AltrepExtract;pub use altrep_data::AltrepLen;pub use altrep_data::IterComplexData;pub use altrep_data::IterIntCoerceData;pub use altrep_data::IterIntData;pub use altrep_data::IterIntFromBoolData;pub use altrep_data::IterListData;pub use altrep_data::IterLogicalData;pub use altrep_data::IterRawData;pub use altrep_data::IterRealCoerceData;pub use altrep_data::IterRealData;pub use altrep_data::IterState;pub use altrep_data::IterStringData;pub use altrep_data::Logical;pub use altrep_data::Sortedness;pub use altrep_data::SparseIterComplexData;pub use altrep_data::SparseIterIntData;pub use altrep_data::SparseIterLogicalData;pub use altrep_data::SparseIterRawData;pub use altrep_data::SparseIterRealData;pub use altrep_data::SparseIterState;pub use altrep_data::StreamingIntData;pub use altrep_data::StreamingRealData;pub use altrep_data::WindowedIterIntData;pub use altrep_data::WindowedIterRealData;pub use altrep_data::WindowedIterState;pub use altrep::RBase;pub use altrep_sexp::AltrepSexp;pub use altrep_sexp::ensure_materialized;pub use altrep_traits::AltrepGuard;pub use into_r::Altrep;pub use into_r::IntoR;pub use into_r::IntoRAltrep;pub use into_r_error::IntoRError;pub use into_r_as::IntoRAs;pub use into_r_as::StorageCoerceError;pub use worker::is_r_main_thread;pub use worker::with_r_thread;pub use thread::DEFAULT_R_STACK_SIZE;pub use thread::RThreadBuilder;pub use ffi_guard::GuardMode;pub use ffi_guard::guarded_ffi_call;pub use ffi_guard::guarded_ffi_call_with_fallback;pub use dataframe::DataFrameError;pub use dataframe::DataFrameView;pub use error::r_warning;pub use rng::RngGuard;pub use rng::with_rng;pub use from_r::SexpError;pub use from_r::SexpLengthError;pub use from_r::SexpNaError;pub use from_r::SexpTypeError;pub use from_r::TryFromSexp;pub use expression::RCall;pub use expression::REnv;pub use expression::RSymbol;pub use coerce::Coerce;pub use coerce::CoerceError;pub use coerce::Coerced;pub use coerce::TryCoerce;pub use as_coerce::AsCharacter;pub use as_coerce::AsCoerceError;pub use as_coerce::AsComplex;pub use as_coerce::AsDataFrame;pub use as_coerce::AsDate;pub use as_coerce::AsEnvironment;pub use as_coerce::AsFactor;pub use as_coerce::AsFunction;pub use as_coerce::AsInteger;pub use as_coerce::AsList as AsListCoerce;pub use as_coerce::AsLogical;pub use as_coerce::AsMatrix;pub use as_coerce::AsNumeric;pub use as_coerce::AsPOSIXct;pub use as_coerce::AsRaw;pub use as_coerce::AsVector;pub use as_coerce::SUPPORTED_AS_GENERICS;pub use as_coerce::is_supported_as_generic;pub use convert::AsDisplay;pub use convert::AsDisplayVec;pub use convert::AsExternalPtr;pub use convert::AsExternalPtrExt;pub use convert::AsFromStr;pub use convert::AsFromStrVec;pub use convert::AsList;pub use convert::AsListExt;pub use convert::AsNamedList;pub use convert::AsNamedListExt;pub use convert::AsNamedVector;pub use convert::AsNamedVectorExt;pub use convert::AsRNative;pub use convert::AsRNativeExt;pub use convert::Collect;pub use convert::CollectNA;pub use convert::CollectNAInt;pub use convert::CollectStrings;pub use convert::DataFrame;pub use convert::IntoDataFrame;pub use convert::ToDataFrame;pub use convert::ToDataFrameExt;pub use into_r::Lazy;pub use list::IntoList;pub use list::List;pub use list::ListAccumulator;pub use list::ListBuilder;pub use list::ListMut;pub use list::NamedList;pub use list::TryFromList;pub use list::collect_list;pub use missing::Missing;pub use missing::is_missing_arg;pub use named_vector::AtomicElement;pub use named_vector::NamedVector;pub use strvec::ProtectedStrVec;pub use strvec::ProtectedStrVecCowIter;pub use strvec::ProtectedStrVecIter;pub use strvec::StrVec;pub use strvec::StrVecBuilder;pub use strvec::StrVecCowIter;pub use strvec::StrVecIter;pub use typed_list::TypeSpec;pub use typed_list::TypedEntry;pub use typed_list::TypedList;pub use typed_list::TypedListError;pub use typed_list::TypedListSpec;pub use typed_list::actual_type_string;pub use typed_list::sexptype_name;pub use typed_list::validate_list;pub use externalptr::ErasedExternalPtr;pub use externalptr::ExternalPtr;pub use externalptr::ExternalSlice;pub use externalptr::IntoExternalPtr;pub use externalptr::TypedExternal;pub use externalptr::altrep_data1_as;pub use externalptr::altrep_data1_as_unchecked;pub use externalptr::altrep_data1_mut;pub use externalptr::altrep_data1_mut_unchecked;pub use externalptr::altrep_data2_as;pub use externalptr::altrep_data2_as_unchecked;pub use gc_protect::OwnedProtect;pub use gc_protect::ProtectIndex;pub use gc_protect::ProtectScope;pub use gc_protect::Protector;pub use gc_protect::ReprotectSlot;pub use gc_protect::Root;pub use protect_pool::ProtectKey;pub use protect_pool::ProtectPool;pub use refcount_protect::Arena;pub use refcount_protect::ArenaGuard;pub use refcount_protect::HashMapArena;pub use refcount_protect::MapStorage;pub use refcount_protect::RefCountedArena;pub use refcount_protect::RefCountedGuard;pub use refcount_protect::ThreadLocalArena;pub use refcount_protect::ThreadLocalArenaOps;pub use refcount_protect::ThreadLocalHashArena;pub use allocator::RAllocator;pub use abi::mx_base_vtable;pub use abi::mx_erased;pub use abi::mx_meth;pub use abi::mx_tag;pub use trait_abi::TraitView;pub use markers::PrefersDataFrame;pub use markers::PrefersExternalPtr;pub use markers::PrefersList;pub use markers::PrefersRNativeType;pub use adapter_traits::RClone;pub use adapter_traits::RCopy;pub use adapter_traits::RDebug;pub use adapter_traits::RDefault;pub use adapter_traits::RDisplay;pub use adapter_traits::RError;pub use adapter_traits::RExtend;pub use adapter_traits::RFromIter;pub use adapter_traits::RFromStr;pub use adapter_traits::RHash;pub use adapter_traits::RIterator;pub use adapter_traits::RMakeIter;pub use adapter_traits::ROrd;pub use adapter_traits::RPartialOrd;pub use adapter_traits::RToVec;pub use rarray::RArray;pub use rarray::RArray3D;pub use rarray::RMatrix;pub use rarray::RVector;pub use match_arg::MatchArg;pub use match_arg::MatchArgError;pub use match_arg::choices_sexp;pub use match_arg::match_arg_from_sexp;pub use factor::Factor;pub use factor::FactorMut;pub use factor::FactorOptionVec;pub use factor::FactorVec;pub use factor::RFactor;pub use factor::build_factor;pub use factor::build_levels_sexp;pub use factor::build_levels_sexp_cached;pub use factor::factor_from_sexp;
Modules§
- abi
- ABI types for cross-package trait dispatch.
- adapter_
traits - Built-in adapter traits for std library traits.
- allocator
- R-backed global allocator for Rust.
- altrep
- Core ALTREP types and registration traits.
- altrep_
bridge - Unsafe ALTREP trampolines and installers bridging safe traits to R’s C ABI.
- altrep_
data - High-level ALTREP data traits.
- altrep_
ext - Extension trait for SEXP providing ALTREP-specific accessors.
- altrep_
impl - ALTREP implementation utilities.
- altrep_
sexp AltrepSexp— a!Send + !Syncwrapper for ALTREP vectors.- altrep_
traits - Safe, idiomatic ALTREP trait hierarchy mirroring R’s method tables.
- as_
coerce - Traits for R’s
as.<class>()coercion functions. - backtrace
- Configurable panic hook for miniextendr-based R packages.
- cached_
class - Cached R class attribute SEXPs.
- coerce
- Type coercion traits for converting Rust types to R native types.
- condition
- Structured error adapter for
std::error::Error. - convert
- Wrapper helpers to force specific
IntoRrepresentations. - dataframe
- Runtime wrapper for R
data.frameobjects. - dots
- Support for R
...arguments represented as a validated list. R’s...(variadic arguments) support. - encoding
- Encoding / locale probing utilities.
- error
- Error handling helpers for R API calls.
- error_
value - Tagged error value transport for
#[miniextendr(error_in_r)]mode. - expression
- Safe wrappers for R expression evaluation.
- externalptr
ExternalPtr<T>— a Box-like owned pointer that wraps R’s EXTPTRSXP.- externalptr_
std TypedExternalimplementations for standard library types.- factor
- Factor support for enum ↔ R factor conversions.
- ffi
- Raw R FFI bindings and low-level SEXP utilities.
- ffi_
guard - Unified FFI guard for catching panics at Rust-R boundaries.
- from_r
- Conversions from R SEXP to Rust types.
- gc_
protect - GC protection tools built on R’s PROTECT stack.
- init
- Package initialization (
miniextendr_init!support). - into_r
- Conversions from Rust types to R SEXP.
- into_
r_ as - Storage-directed conversion to R.
- into_
r_ error - Error types for fallible
IntoRconversions. - list
- Thin wrapper around R list (
VECSXP). - markers
- Marker traits for proc-macro derived types. Marker traits for proc-macro derived types.
- match_
arg match.arg-style string conversion for enums.- missing
- Support for R’s missing arguments.
- mx_abi
- C-callable mx_abi functions (mx_wrap, mx_get, mx_query, mx_abi_register).
- named_
vector - Named atomic vector wrapper for HashMap/BTreeMap ↔ named R atomic vector conversions.
- optionals
- Optional feature integrations with third-party crates.
- panic_
telemetry - Structured panic telemetry for debugging Rust panics that become R errors.
- prelude
- Convenience re-exports for common miniextendr items.
- preserve
- Deprecated: Use
ProtectPoolorR_PreserveObjectinstead. This module remains for benchmark comparisons only. Seeanalysis/gc-protection-benchmarks-results.md. - protect_
pool - VECSXP-backed protection pool with generational keys.
- r_
memory - Utilities for recovering R SEXPs from raw data pointers.
- rarray
- N-dimensional R arrays with const generic dimension count. N-dimensional R arrays with const generic dimension count.
- refcount_
protect - Reference-counted GC protection using a map + VECSXP backing.
- registry
- Automatic registration internals.
- rng
- RNG (Random Number Generation) utilities for R interop.
- s4_
helpers - S4 slot access and class checking helpers.
- strict
- Strict conversion helpers for
#[miniextendr(strict)]. - strvec
- Thin wrapper around R character vector (
STRSXP). - thread
- Thread safety utilities for calling R from non-main threads.
- trait_
abi - Runtime support for trait ABI operations.
- typed_
list - Typed list validation for structured R list arguments.
- unwind_
protect - Safe API for R’s
R_UnwindProtect - worker
- Worker thread infrastructure for safe Rust-R FFI.
Macros§
- define_
thread_ local_ arena - Macro to define a thread-local arena with a specific map type.
- impl_
altcomplex_ from_ data - Generate ALTREP trait implementations for a type that implements AltComplexData.
- impl_
altinteger_ from_ data - Generate ALTREP trait implementations for a type that implements AltIntegerData.
- impl_
altlist_ from_ data - Generate ALTREP trait implementations for a type that implements AltListData.
- impl_
altlogical_ from_ data - Generate ALTREP trait implementations for a type that implements AltLogicalData.
- impl_
altraw_ from_ data - Generate ALTREP trait implementations for a type that implements AltRawData.
- impl_
altreal_ from_ data - Generate ALTREP trait implementations for a type that implements AltRealData.
- impl_
altstring_ from_ data - Generate ALTREP trait implementations for a type that implements AltStringData.
- impl_
inferbase_ complex - Implement
InferBasefor a complex ALTREP data type. - impl_
inferbase_ integer - Implement
InferBasefor an integer ALTREP data type. - impl_
inferbase_ list - Implement
InferBasefor a list ALTREP data type. - impl_
inferbase_ logical - Implement
InferBasefor a logical ALTREP data type. - impl_
inferbase_ raw - Implement
InferBasefor a raw ALTREP data type. - impl_
inferbase_ real - Implement
InferBasefor a real ALTREP data type. - impl_
inferbase_ string - Implement
InferBasefor a string ALTREP data type. - impl_
option_ try_ from_ sexp - Implement
TryFromSexp for Option<T>where T already implements TryFromSexp. - impl_
typed_ external - Generate
TypedExternalandIntoExternalPtrimpls for a concrete monomorphization of a generic type. - impl_
vec_ option_ try_ from_ sexp_ list - Implement
TryFromSexp for Vec<Option<T>>from R list (VECSXP). - impl_
vec_ try_ from_ sexp_ list - Implement
TryFromSexp for Vec<T>from R list (VECSXP). - list
- Construct an R list from Rust values.
- miniextendr_
init - Generate the
R_init_*entry point for a miniextendr R package. - r_print
- Print to R’s console (like
print!). - r_
println - Print to R’s console with a newline (like
println!). - report_
growth - Print and reset all growth counters.
- track_
growth - Track a collection growth (reallocation) event.
- typed_
list - Create a
TypedListSpecfor validating...arguments or lists.
Statics§
Attribute Macros§
- miniextendr
- Export Rust items to R.
- r_
ffi_ checked - Generate thread-safe wrappers for R FFI functions.
Derive Macros§
- Altrep
- Derive ALTREP registration for a data struct.
- Altrep
Complex - Derive macro for ALTREP complex vector data types.
- Altrep
Integer - Derive macro for ALTREP integer vector data types.
- Altrep
List - Derive macro for ALTREP list vector data types.
- Altrep
Logical - Derive macro for ALTREP logical vector data types.
- Altrep
Raw - Derive macro for ALTREP raw vector data types.
- Altrep
Real - Derive macro for ALTREP real vector data types.
- Altrep
String - Derive macro for ALTREP string vector data types.
- Data
Frame Row - Derive
DataFrameRow: generates a companion*DataFrametype with collection fields, plusIntoR/TryFromSexp/IntoDataFrameimpls for seamless R data.frame conversion. - External
Ptr - Derive macro for implementing
TypedExternalon a type. - Into
List - Derive
IntoListfor a struct (Rust → R list). - Match
Arg - Derive
MatchArg: enables conversion between Rust enums and R character strings withmatch.argsemantics (partial matching, informative errors). - Prefer
Data Frame - Derive
PreferDataFrame: when a type implements bothIntoDataFrame(viaDataFrameRow) and other conversion paths, this selects data.frame as the defaultIntoRconversion. - Prefer
External Ptr - Derive
PreferExternalPtr: when a type implements bothExternalPtrand other conversion paths (e.g.,IntoList), this selectsExternalPtrwrapping as the defaultIntoRconversion. - Prefer
List - Derive
PrefersList: when a type implements bothIntoListandExternalPtr, this selects list as the defaultIntoRconversion. - PreferR
Native Type - Derive
PreferRNativeType: when a newtype wraps anRNativeTypeand also implements other conversions, this selects the native R vector conversion as the defaultIntoRpath. - RFactor
- Derive
RFactor: enables conversion between Rust enums and R factors. - RNative
Type - Derive macro for implementing
RNativeTypeon a newtype wrapper. - TryFrom
List - Derive
TryFromListfor a struct (R list → Rust).