Skip to main content

Module externalptr

Module externalptr 

Source
Expand description

ExternalPtr<T> — a Box-like owned pointer that wraps R’s EXTPTRSXP.

This provides ownership semantics similar to Box<T>, with the key difference that cleanup is deferred to R’s garbage collector via finalizers.

§Submodules

ModuleContents
altrep_helpersALTREP data1/data2 slot access helpers + Sidecar marker type

§Core Types

PartialEq/PartialOrd compare the pointee values (like Box<T>). Use ptr_eq when you care about pointer identity, and as_ref()/as_mut() for explicit by-value comparisons.

§Protection Strategies in miniextendr

miniextendr provides three complementary protection mechanisms for different scenarios:

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

§When to Use ExternalPtr

Use ExternalPtr (this module) when:

  • You want R to own a Rust value
  • The Rust value should be dropped when R garbage collects the pointer
  • You’re exposing Rust structs to R code

Use gc_protect instead when:

  • You’re allocating temporary R objects during computation
  • Protection is short-lived (within a single .Call)

Use preserve instead when:

  • You need R objects (not Rust values) to survive across .Calls
  • You need arbitrary-order release of protections

§How ExternalPtr Protection Works

┌─────────────────────────────────────────────────────────────────┐
│  ExternalPtr<MyStruct>::new(value)                              │
│  ├── Rf_protect() during construction (temporary)               │
│  ├── R_MakeExternalPtr() creates EXTPTRSXP                      │
│  ├── R_RegisterCFinalizerEx() registers cleanup callback        │
│  └── Rf_unprotect() after construction complete                 │
│                                                                 │
│  Return to R → R now owns the EXTPTRSXP                         │
│  ├── SEXP is live as long as R has references                   │
│  └── Rust value is accessible via ExternalPtr::wrap_sexp()      │
│                                                                 │
│  R GC runs → finalizer called → Rust Drop executes              │
└─────────────────────────────────────────────────────────────────┘

§Type Identification

Type safety is enforced via Any::downcast (Rust’s TypeId). R symbols in the tag and prot slots are retained for display and error messages.

Internally, data is stored as Box<Box<dyn Any>> — a thin pointer (fits in R’s R_ExternalPtrAddr) pointing to a fat pointer (carries the Any vtable for runtime downcasting).

The tag slot holds a symbol (type name, for display). The prot slot holds a VECSXP (list) with two elements:

  • Index 0: SYMSXP (interned type ID symbol, for error messages)
  • Index 1: User-protected SEXP slot (for preventing GC of R objects)

§ExternalPtr is Not an R Native Type

Unlike R’s native atomic types (integer, double, character, etc.), external pointers cannot be coerced to vectors or used in R’s vectorized operations. This is an R limitation, not a miniextendr limitation:

> matrix(new("externalptr"), 1, 1)
Error in `as.vector()`:
! cannot coerce type 'externalptr' to vector of type 'any'

If you need your Rust type to participate in R’s vector/matrix operations, consider implementing IntoList (via #[derive(IntoList)]) to convert your struct to a named R list, or use ALTREP to expose Rust iterators as lazy R vectors.

Modules§

altrep_helpers 🔒
ALTREP helpers for ExternalPtr — data1/data2 slot access.

Structs§

ExternalPtr
An owned pointer stored in R’s external pointer SEXP.
ExternalSlice
A slice stored as a standalone struct, suitable for wrapping in ExternalPtr.
RSidecar
Marker type for enabling R sidecar accessors in an ExternalPtr struct.

Enums§

TypeMismatchError
Error returned when type checking fails in try_from_sexp_with_error.

Constants§

PROT_TYPE_ID_INDEX 🔒
Index of the type SYMSXP contained in the prot (a VECSXP list)
PROT_USER_INDEX 🔒
Index of user-protected objects contained in the prot (a VECSXP list)
PROT_VEC_LEN 🔒
Length of the prot list (VECSXP)

Traits§

IntoExternalPtr
Marker trait for types that should be converted to R as ExternalPtr.
TypedExternal
Trait for types that can be stored in an ExternalPtr.

Functions§

altrep_data1_as
Extract the ALTREP data1 slot as a typed ExternalPtr<T>.
altrep_data1_as_unchecked
Extract the ALTREP data1 slot (unchecked version).
altrep_data1_mut
Get a mutable reference to data in ALTREP data1 slot via ErasedExternalPtr.
altrep_data1_mut_unchecked
Get a mutable reference to data in ALTREP data1 slot (unchecked version).
altrep_data2_as
Extract the ALTREP data2 slot as a typed ExternalPtr<T>.
altrep_data2_as_unchecked
Extract the ALTREP data2 slot (unchecked version).
is_type_erased 🔒
release_any 🔒
Non-generic C finalizer called by R’s garbage collector.
sendable_any_ptr_into_ptr 🔒
Get the raw pointer, consuming the sendable wrapper.
sendable_any_ptr_new 🔒
Create a new sendable pointer from a raw *mut Box<dyn Any>.
symbol_name 🔒
Get the type name from a stored symbol SEXP.
type_id_symbol 🔒
Get the namespaced type ID symbol for type checking.
type_id_symbol_unchecked 🔒
Unchecked version of type_id_symbol.
type_symbol 🔒
Get the interned R symbol for a type’s name.
type_symbol_unchecked 🔒
Unchecked version of type_symbol - no thread safety checks.

Type Aliases§

ErasedExternalPtr
Type-erased ExternalPtr for cases where the concrete T is not needed.
SendableAnyPtr 🔒
A wrapper around a raw pointer that implements Send.