Skip to content

Commit

Permalink
Merge pull request #19 from CarolineMorton/add-r
Browse files Browse the repository at this point in the history
Add r
  • Loading branch information
em-baggie authored Dec 22, 2024
2 parents 9f90086 + cfb770c commit 847c140
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 0 deletions.
2 changes: 2 additions & 0 deletions bindings/r/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
rustflags = ["-C", "link-args=-undefined dynamic_lookup"]
13 changes: 13 additions & 0 deletions bindings/r/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "codelist"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["staticlib"]
name = "codelist"
path = "src/lib.rs"
# Build as a dynamic library

[dependencies]
extendr-api = "0.7.1"
13 changes: 13 additions & 0 deletions bindings/r/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Package: codelist
Title: R Wrapper for Rust Functions
Version: 0.1.0
Authors@R:
person("Your Name", "Your Last Name", email = "[email protected]", role = c("aut", "cre"))
Description: Provides R bindings for Rust functions using extendr.
License: MIT + file LICENSE
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
Imports:
rextendr
Config/rextendr/version: 0.3.1
2 changes: 2 additions & 0 deletions bindings/r/NAMESPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
useDynLib(codelist, .registration = TRUE)
export(hello)
16 changes: 16 additions & 0 deletions bindings/r/R/extendr-wrappers.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Generated by extendr: Do not edit by hand

# nolint start

#
# This file was created with the following call:
# .Call("wrap__make_codelist_wrappers", use_symbols = TRUE, package_name = "codelist")

#' @usage NULL
#' @useDynLib codelist, .registration = TRUE
NULL

hello <- function() .Call(wrap__hello)


# nolint end
75 changes: 75 additions & 0 deletions bindings/r/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# R Bindings

This package demonstrates how to call Rust functions from R using extendr.
I (@CarolineMorton) have not yet implemented this with our Codelist library
but rather with a simple "hello world" function.

## Prerequisites

- Install R (version 4.0 or higher recommended)
- macOS: `brew install r`

#### Notes
- My R installation took a long time to complete, so be patient here. It seems like it was broken
because for some reason installing R also means it installs the latest version of Python, Pytorch and
a bunch of other things. I'm not super familiar with R or why it does this but 🤷‍♀️ it might just be a
me problem.
- I think you need to have Xcode installed on macOS to get the C bridge to work.
- I had to add R to my path before I could get into the R console via the terminal:
```bash
R
```
- An alternative is to use RStudio, which is a popular IDE for R.
- You can exit the R console with `q()`. You then get this:
```bash
Save workspace image? [y/n/c]:
```
which i said no to.

## Building and Installing

1. First build the Rust library:
```bash
cd r
cargo build --release
```

This will create a shared library in `target/release/libcodelist.dylib` (macOS) or `target/release/libcodelist.so` (Linux).

2. Open R with the terminal command `R`
and install required packages. If you get an error message when running this, you may also need to install package dependencies for `devtools` first if not already installed:
```r
install.packages("devtools")
install.packages("rextendr")
```

I picked `64` as the mirror I wanted to use.


3. Build and load the package:
```r
rextendr::document()
devtools::document()
devtools::load_all()
```

4. Test that it works:
```r
hello()
```

## Installing Permanently

To install the package permanently:

```r
devtools::build()
devtools::install()
```

After installation, you can use it like any other R package:

```r
library(codelist)
hello()
```
13 changes: 13 additions & 0 deletions bindings/r/src/Makevars
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
LIBDIR = ../target/release
STATLIB = $(LIBDIR)/libcodelist.a
PKG_LIBS = -L$(LIBDIR) -lcodelist

all: C_clean

$(SHLIB): $(STATLIB)

$(STATLIB):
cargo build --lib --release

C_clean:
rm -Rf $(SHLIB) $(STATLIB) $(OBJECTS)
8 changes: 8 additions & 0 deletions bindings/r/src/entrypoint.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// We need to forward routine registration from C to Rust
// to avoid the linker removing the static library.

void R_init_codelist_extendr(void *dll);

void R_init_codelist(void *dll) {
R_init_codelist_extendr(dll);
}
12 changes: 12 additions & 0 deletions bindings/r/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use extendr_api::prelude::*;

#[extendr]
fn hello() -> &'static str {
println!("hello function called");
"hello"
}

extendr_module! {
mod codelist;
fn hello;
}

0 comments on commit 847c140

Please sign in to comment.