Skip to main content

Crate miniextendr_api

Crate miniextendr_api 

Source
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 Drop safety (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:

StrategyModuleLifetimeRelease OrderUse Case
PROTECT stackgc_protectWithin .CallLIFO (stack)Temporary allocations
Preserve listpreserveAcross .CallsAny orderLong-lived R objects
R ownershipExternalPtrUntil R GCsR decidesRust 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 automatically

R 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 GCs

Note: 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

FeatureDescription
nonapiNon-API R symbols (stack controls, mutable DATAPTR). May break with R updates.
rayonParallel iterators via Rayon. Adds RParallelIterator, RParallelExtend.
connectionsExperimental R connection framework. Unstable R API.
indicatifProgress bars via R console. Requires nonapi.
vctrsvctrs class construction (new_vctr, new_rcrd, new_list_of) and #[derive(Vctrs)].
worker-threadWorker thread for panic isolation and Drop safety. Without it, stubs run inline.

§Type Conversions (Scalars & Vectors)

FeatureRust TypeR TypeNotes
eitherEither<L, R>Tries L then RUnion-like dispatch
uuidUuid, Vec<Uuid>characterUUID ↔ string
regexRegexcharacter(1)Compiles pattern from R
urlUrl, Vec<Url>characterValidated URLs
timeOffsetDateTime, DatePOSIXct, DateDate/time conversions
ordered-floatOrderedFloat<f64>numericNaN-orderable floats
num-bigintBigInt, BigUintcharacterArbitrary precision via strings
rust_decimalDecimalcharacterFixed-point decimals
num-complexComplex<f64>complexNative R complex support
indexmapIndexMap<String, T>named listPreserves insertion order
bitflagsRFlags<T>integerBitflags ↔ integer
bitvecRBitVeclogicalBit vectors ↔ logical
tinyvecTinyVec<[T; N]>, ArrayVec<[T; N]>vectorsSmall-vector optimization

§Matrix & Array Libraries

FeatureTypesConversions
ndarrayArray1Array6, ArrayD, viewsR vectors/matrices ↔ ndarray
nalgebraDVector, DMatrixR vectors/matrices ↔ nalgebra

§Serialization

FeatureTraits/ModulesDescription
serdeRSerializeNative, RDeserializeNativeDirect Rust ↔ R native serialization
serde_jsonRSerialize, RDeserializeJSON string serialization (includes serde)
borshBorsh<T>Binary serialization ↔ raw vectors via Borsh

§Adapter Traits (Generic Operations)

FeatureTraitsUse Case
num-traitsRNum, RSigned, RFloatGeneric numeric operations
bytesRBuf, RBufMutByte buffer operations

§Text & Data Processing

FeatureTypes/FunctionsDescription
aho-corasickAhoCorasick, aho_compileFast multi-pattern string search
tomlTomlValue, toml_from_strTOML parsing and serialization
tabledtable_to_stringASCII/Unicode table formatting
sha2sha256_str, sha512_bytesCryptographic hashing

§Random Number Generation

FeatureTypesDescription
randRRng, RDistributionsWraps R’s RNG with rand traits
rand_distrRe-exports rand_distrAdditional distributions (Normal, Exp, etc.)

§Binary Data

FeatureTypesDescription
raw_conversionsRaw<T>, RawSlice<T>POD types ↔ raw vectors via bytemuck

§Project-wide Defaults (mutually exclusive where noted)

FeatureDescription
default-r6Default class system: R6 (mutually exclusive with default-s7)
default-s7Default class system: S7 (mutually exclusive with default-r6)
default-workerDefault to worker thread dispatch (implies worker-thread)
default-strictDefault to strict mode for lossy integer conversions
default-coerceDefault to coerce mode for type conversions

§Development / Diagnostics

FeatureDescription
doc-lintWarn on roxygen doc comment mismatches (enabled by default)
macro-coverageExpose macro coverage test module for cargo expand auditing
debug-preserveEnable preserve::count() diagnostic helpers (tests/benchmarks only)
growth-debugTrack and report collection growth events (zero-cost when off)
refcount-fast-hashUse 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 + !Sync wrapper 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 IntoR representations.
dataframe
Runtime wrapper for R data.frame objects.
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
TypedExternal implementations 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 IntoR conversions.
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 ProtectPool or R_PreserveObject instead. This module remains for benchmark comparisons only. See analysis/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 InferBase for a complex ALTREP data type.
impl_inferbase_integer
Implement InferBase for an integer ALTREP data type.
impl_inferbase_list
Implement InferBase for a list ALTREP data type.
impl_inferbase_logical
Implement InferBase for a logical ALTREP data type.
impl_inferbase_raw
Implement InferBase for a raw ALTREP data type.
impl_inferbase_real
Implement InferBase for a real ALTREP data type.
impl_inferbase_string
Implement InferBase for a string ALTREP data type.
impl_option_try_from_sexp
Implement TryFromSexp for Option<T> where T already implements TryFromSexp.
impl_typed_external
Generate TypedExternal and IntoExternalPtr impls 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 TypedListSpec for validating ... arguments or lists.

Statics§

ALTREP_DLL_INFO 🔒
ALTREP_PKG_NAME_PTR 🔒

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.
AltrepComplex
Derive macro for ALTREP complex vector data types.
AltrepInteger
Derive macro for ALTREP integer vector data types.
AltrepList
Derive macro for ALTREP list vector data types.
AltrepLogical
Derive macro for ALTREP logical vector data types.
AltrepRaw
Derive macro for ALTREP raw vector data types.
AltrepReal
Derive macro for ALTREP real vector data types.
AltrepString
Derive macro for ALTREP string vector data types.
DataFrameRow
Derive DataFrameRow: generates a companion *DataFrame type with collection fields, plus IntoR / TryFromSexp / IntoDataFrame impls for seamless R data.frame conversion.
ExternalPtr
Derive macro for implementing TypedExternal on a type.
IntoList
Derive IntoList for a struct (Rust → R list).
MatchArg
Derive MatchArg: enables conversion between Rust enums and R character strings with match.arg semantics (partial matching, informative errors).
PreferDataFrame
Derive PreferDataFrame: when a type implements both IntoDataFrame (via DataFrameRow) and other conversion paths, this selects data.frame as the default IntoR conversion.
PreferExternalPtr
Derive PreferExternalPtr: when a type implements both ExternalPtr and other conversion paths (e.g., IntoList), this selects ExternalPtr wrapping as the default IntoR conversion.
PreferList
Derive PrefersList: when a type implements both IntoList and ExternalPtr, this selects list as the default IntoR conversion.
PreferRNativeType
Derive PreferRNativeType: when a newtype wraps an RNativeType and also implements other conversions, this selects the native R vector conversion as the default IntoR path.
RFactor
Derive RFactor: enables conversion between Rust enums and R factors.
RNativeType
Derive macro for implementing RNativeType on a newtype wrapper.
TryFromList
Derive TryFromList for a struct (R list → Rust).