extendr - extending R with Rust 🦀

Github Actions Build Status Crates.io Documentation License: MIT

rextendr logo

Build blazingly fast R packages 📦 with ease. The extendr ecosystem is developer-friendly and CRAN-ready. extendr let’s you write ergonomic and idomatic Rust without having to worry about R’s internals (much 😅).

Getting Started

  • Don’t have Rust installed yet? Start here.
  • Familiar with Rust and want to get your hands dirty? Follow along with a complete example.

The ecosystem

Rust crates 🦀 :

  • extendr-api—ergonomic, opinionated, and safe interface between R and Rust
  • extendr-engine—embed and use R in Rust
  • extendr-ffi—hand-crafted bindings to R’s C-API

R packages 📦 :

  • {rextendr}—A {usethis}-like package that scaffolds extendr-powered R packages

Quickstart

We recommend using the development version of {rextendr} from GitHub.

# Install from CRAN
install.packages("rextendr")

# Development version
remotes::install_github("extendr/rextendr")

# create a new R package
usethis::create_package("helloextendr")

# Use extendr
rextendr::use_extendr()

# Document and build the package
rextendr::document()

# run hello_world()
hello_world()
#> [1] "Hello, world!"

Example: calling structs from R

use extendr_api::prelude::*;

#[extendr]
#[derive(Debug)]
struct Person {
    pub name: String,
}

#[extendr]
impl Person {
    fn new() -> Self {
        Self { name: "".to_string() }
    }

    fn set_name(&mut self, name: &str) {
        self.name = name.to_string();
    }

    fn name(&self) -> &str {
        self.name.as_str()
    }
}

#[extendr]
fn my_function() { }

// Macro to generate exports
extendr_module! {
    mod classes;
    impl Person;
    fn my_function;
}

The #[extendr] attribute causes the compiler to generate wrapper and registration functions for R which are called when the package is loaded, thus allowing one to access Rust functions and structures in an R session:

# call function
my_function()

# create Person object
p <- Person$new()
p$set_name("foo")
p$name()   # "foo" is returned

This, of course, is just the tip of the iceberg, for there are many ways to use extendr in R: