Skip to main content

Crate miniextendr_macros

Crate miniextendr_macros 

Source
Expand description

§miniextendr-macros - Procedural macros for Rust <-> R interop

This crate provides the procedural macros that power miniextendr’s code generation. Most users should depend on miniextendr-api and use its re-exports, but this crate can be used directly when you only need macros.

Primary macros and derives:

  • #[miniextendr] on functions, impl blocks, trait defs, and trait impls.
  • #[r_ffi_checked] for main-thread routing of C-ABI wrappers.
  • Derives: ExternalPtr, RNativeType, ALTREP derives, RFactor.
  • Helpers: typed_list for typed list builders.

R wrapper generation is driven by Rust doc comments (roxygen tags are extracted). The document binary collects these wrappers and writes R/miniextendr_wrappers.R during package build.

§Quick start

use miniextendr_api::miniextendr;

#[miniextendr]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

§Macro expansion pipeline

§Overview

┌──────────────────────────────────────────────────────────────────────────┐
│                         #[miniextendr] on fn                             │
│                                                                          │
│  1. Parse: syn::ItemFn → MiniextendrFunctionParsed                       │
│  2. Analyze return type (Result<T>, Option<T>, raw SEXP, etc.)           │
│  3. Generate:                                                            │
│     ├── C wrapper: extern "C-unwind" fn C_<name>(call: SEXP, ...) → SEXP │
│     ├── R wrapper: const R_WRAPPER_<NAME>: &str = "..."                  │
│     └── Registration: const call_method_def_<name>: R_CallMethodDef      │
│  4. Original function preserved (with added attributes)                  │
└──────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────┐
│                    #[miniextendr(env|r6|s3|s4|s7)] on impl               │
│                                                                          │
│  1. Parse: syn::ItemImpl → extract methods                               │
│  2. For each method:                                                     │
│     ├── Generate C wrapper (handles self parameter)                      │
│     ├── Generate R method wrapper string                                 │
│     └── Generate registration entry                                      │
│  3. Generate class definition code per class system:                     │
│     ├── env: new.env() + method assignment                               │
│     ├── r6: R6Class() definition                                         │
│     ├── s3: S3 generics + methods                                        │
│     ├── s4: setClass() + setMethod()                                     │
│     └── s7: new_class() definition                                       │
│  4. Emit const with combined R code                                      │
└──────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────┐
│                         #[miniextendr] on trait                          │
│                                                                          │
│  1. Parse: syn::ItemTrait → extract method signatures                    │
│  2. Generate:                                                            │
│     ├── Trait tag constant: const TAG_<TRAIT>: mx_tag = ...              │
│     ├── Vtable struct: struct __vtable_<Trait> { ... }                   │
│     └── CCalls table: static MX_CCALL_<TRAIT>: [...] = ...               │
│  3. Original trait preserved                                             │
└──────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────┐
│                    #[miniextendr] impl Trait for Type                    │
│                                                                          │
│  1. Parse: syn::ItemImpl (trait impl)                                    │
│  2. Generate:                                                            │
│     ├── Vtable instance: static __VTABLE_<TRAIT>_FOR_<TYPE>: ...         │
│     ├── Wrapper struct: struct __MxWrapper<Type> { erased, data }        │
│     ├── Query function: fn __mx_query_<type>(tag) → vtable ptr           │
│     └── Base vtable: static __MX_BASE_VTABLE_<TYPE>: ...                 │
│  3. Original impl preserved                                              │
└──────────────────────────────────────────────────────────────────────────┘

§Key Modules

ModulePurpose
miniextendr_fnFunction parsing and attribute handling
c_wrapper_builderC wrapper generation (extern "C-unwind")
r_wrapper_builderR wrapper code generation
rust_conversion_builderRust→SEXP return value conversion
miniextendr_implimpl Type block processing
r_class_formatterClass system code generation (env/r6/s3/s4/s7)
miniextendr_traitTrait ABI metadata generation
miniextendr_impl_traitimpl Trait for Type vtable generation
altrep / altrep_deriveALTREP struct derivation
externalptr_derive#[derive(ExternalPtr)]
roxygenRoxygen doc comment handling

§Generated Symbol Naming

For a function my_func:

  • C wrapper: C_my_func
  • R wrapper const: R_WRAPPER_MY_FUNC
  • Registration: call_method_def_my_func

For a type MyType with trait Counter:

  • Vtable: __VTABLE_COUNTER_FOR_MYTYPE
  • Wrapper: __MxWrapperMyType
  • Query: __mx_query_mytype

§Return Type Handling

The return_type_analysis module determines how to convert Rust returns to SEXP:

Rust TypeStrategyR Result
T: IntoR.into_sexp()Converted value
Result<T, E>Unwrap or R errorValue or error
Option<T>Some → value, NoneNULLValue or NULL
SEXPPass throughRaw SEXP
()Invisible NULLinvisible(NULL)

Use #[miniextendr(unwrap_in_r)] to return Result<T, E> to R without unwrapping.

§Thread Strategy

By default, #[miniextendr] functions run on R’s main thread. Opt into worker-thread execution with #[miniextendr(worker)] (requires the worker-thread feature on miniextendr-api). A worker opt-in is ignored when the signature requires main-thread execution (returns/takes SEXP, uses variadic dots, or sets check_interrupt).

Note: ExternalPtr<T> is Send — it can be returned from worker thread functions. All R API operations on ExternalPtr are serialized through with_r_thread.

§Class Systems

The r_class_formatter module generates R code for different class systems:

SystemGenerated R CodeSelf Parameter
envnew.env() with methodsself environment
r6R6Class()self environment
s3structure() + genericsFirst argument
s4setClass() + setMethod()First argument
s7new_class()self property

Modules§

altrep 🔒
ALTREP registration code generation.
altrep_derive 🔒
Derive macros for ALTREP data traits.
c_wrapper_builder 🔒
Unified C wrapper generation for standalone functions and impl methods.
dataframe_derive 🔒
Derive macros for bidirectional row ↔ dataframe conversions.
externalptr_derive 🔒
#[derive(ExternalPtr)] - ExternalPtr Support
factor_derive 🔒
#[derive(RFactor)] - Enum ↔ R Factor Support
lifecycle 🔒
Lifecycle support for R package deprecation management.
list_derive 🔒
List and Preference Derive Macros
list_macro 🔒
Parser for the list! macro.
match_arg_derive 🔒
#[derive(MatchArg)] - Enum ↔ R String with match.arg Support
match_arg_keys 🔒
Write-time placeholder & symbol-name formatting for the match_arg pipeline.
method_return_builder 🔒
Shared utilities for handling method return values in R wrapper generation.
miniextendr_fn 🔒
Function signature parsing for #[miniextendr].
miniextendr_impl 🔒
Impl-block Parsing and Wrapper Generation
miniextendr_impl_trait 🔒
#[miniextendr] on trait impls - Trait Implementation Registration
miniextendr_trait 🔒
Trait Support for #[miniextendr]
naming 🔒
Naming helpers for the static symbols the #[miniextendr] attribute emits.
r_class_formatter 🔒
Shared utilities for R class wrapper generation.
r_preconditions 🔒
R-side precondition generation for type checking.
r_wrapper_builder 🔒
Shared utilities for building R wrapper code.
return_type_analysis 🔒
Return type analysis for #[miniextendr] functions.
roxygen 🔒
Roxygen tag extraction and processing for R wrapper generation.
rust_conversion_builder 🔒
Shared utilities for converting R SEXP parameters to Rust types.
struct_enum_dispatch 🔒
Dispatch #[miniextendr] on structs and enums to the appropriate derive helpers.
type_inspect 🔒
Lightweight type-introspection helpers shared by parsing and codegen.
typed_external_macro 🔒
impl_typed_external! — explicit monomorphization of TypedExternal for generic types.
typed_list 🔒
Parser for the typed_list! macro.
util 🔒
Small cross-cutting helpers used by multiple macro modules.
vctrs_generics 🔒
Known vctrs S3 generic names used to auto-insert @importFrom vctrs.

Macros§

__mx_trait_impl_expand 👻
Internal proc macro used by TPIE (Trait-Provided Impl Expansion).
impl_typed_external
Generate TypedExternal and IntoExternalPtr impls for a concrete monomorphization of a generic type.
list
Construct an R list from Rust values.
miniextendr_init
Generate the R_init_* entry point for a miniextendr R package.
typed_list
Create a TypedListSpec for validating ... arguments or lists.

Functions§

apply_return_pref 🔒
Maps a ReturnPref attribute value onto an auto-detected ReturnHandling.
build_match_arg_helpers 🔒
Emit the extern "C-unwind" helper + R_CallMethodDef registration for each standalone-fn match_arg param.
validate_extern_signature 🔒
Validate the signature of an extern "C-unwind" fn exported via #[miniextendr].

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).