Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
RパッケージでRustを使うには: extendr入門 / extendr-pkg-dev
Search
yutannihilation
May 30, 2021
Programming
8.1k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RパッケージでRustを使うには: extendr入門 / extendr-pkg-dev
第92回R勉強会
の発表スライドです。
(
ウェブ版
をPDFエクスポートしたものですが、Slidevの使い方がわからず画像が消えてしまっています...)
yutannihilation
May 30, 2021
More Decks by yutannihilation
See All by yutannihilation
🦀
yutannihilation
2
870
rayshader入門 / rayshader-tokyor88
yutannihilation
0
1.2k
RとApache Arrow / r-and-apache-arrow
yutannihilation
4
7.6k
そろそろ使ってみませんかApache Arrow / why-dont-you-arrow-now
yutannihilation
2
1.2k
A Graphical Introduction to tidyr's pivot_*()
yutannihilation
5
5.4k
tidyr 1.0.0の新機能 pivot_*() / tidyr-pivot
yutannihilation
4
11k
RとApache Arrow
yutannihilation
0
3.5k
Yet Another Introduction to tidyeval
yutannihilation
10
8.4k
Introduction to gghighlight
yutannihilation
6
3k
Other Decks in Programming
See All in Programming
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
160
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
340
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
190
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
240
残高管理から台帳サービスへの進化
artoy
1
210
HTML-in-Canvasで作る未来のWeb UI表現
clockmaker
5
5.8k
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
230
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
2
1.3k
自作Discord音声botをLambda MicroVMsに移行した話 / Migrating My Discord Voice Bot to Lambda MicroVMs
akihisaikeda
0
150
Groovy as a human and AI friendly programming language
paulk
0
110
Agentic Software Factoryに、すごく賢いIF文を。 / super smart IF statement into the Agentic Software Factory.
rkaga
8
2.4k
見えないものを探る要求要件定義に必要な基本的思考 / invisible-requirement-thinking
minodriven
15
8.8k
Featured
See All Featured
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.9k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
620
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
420
GraphQLとの向き合い方2022年版
quramy
50
15k
RailsConf 2023
tenderlove
30
1.6k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.8k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
950
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
850
Agile that works and the tools we love
rasmusluckow
331
22k
How STYLIGHT went responsive
nonsquared
100
6.3k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2.1k
Transcript
Rパッケージで Rustを使うには: extendr入門 Hiroaki Yutani (@yutannihilation) Tokyo.R#92
ドーモ! : @yutannihilation 好きな言語: R、Rust、忍殺語 最近の趣味: ガスコンロの電子楽器 をつくってます
Rユーザのための RStudio[実践]入 門 第2版! https://gihyo.jp/book/2021/978- 4-297-12170-9 紙は6月3日、電子は5 月31日発売です。
extendr
extendrとは? RustとRを連携させるためのフレームワーク RからRustを使うだけではなく、RustからRを使 うこともできる(つまり、Rustの中でggplot2を 呼び出してプロットしたり、とかできるらしい) なぜか私も中の人です…
なぜRust? → そこにRustがあるから!! (誰か教えてください…)
※今日話さないこと Rustの何が素晴らしいのか Rust入門 Rust側からRを操作する方法 R MarkdownのRust engineとか、パッケージ外 でのextendrの使いみち
extendrの愉快な仲間たち libR-sys(Rust): RのC APIにbindgenで生成したバインディング extendr(Rust): libR-sysを使いやすくラップしたフレームワーク rextendr(Rパッケージ): Rからextendrを使うためのユーティリティ (usethisパッケージのような立ち位置)
準備
Rustのインストール macOS / Linux: ふつうにRustをインストール(ググる) Windows MSVCのtoolchainに加えて、64bit/32bit GNU用 のtargetを追加する必要がある rustup
default stable-msvc rustup target add x86_64-pc-windows-gnu rustup target add i686-pc-windows-gnu
rextendrパッケージのインストール GitHubからインストール devtools::install_github("extendr/rextendr")
パッケージのセットアップ
RStudioからパッケージ作成
Roxygenを使うように設定変更 NAMESPACEを上書き Build optionsを設定 Build > Configure Build Tools… >
Generate documentation with Roxygen に を入れる 不要なファイルを削除 R/hello.R man/hello.Rd usethis::use_namespace() ` ` ` `
extendrのデフォルト設定を生成 rextendr::use_extendr() ✓ Creating src/rust/src. ✓ Writing 'src/entrypoint.c' ✓ Writing
'src/Makevars' ✓ Writing 'src/Makevars.win' ✓ Writing 'src/.gitignore' ✓ Writing src/rust/Cargo.toml. ✓ Writing 'src/rust/src/lib.rs' ✓ Writing 'R/extendr-wrappers.R' ✓ Finished configuring extendr for package myextendr. • Please update the system requirement in DESCRIPTION file. • Please run `rextendr::document()` for changes to take effect
生成されたファイル . ├── R │ └── extendr-wrappers.R ... └── src
├── Makevars ├── Makevars.win ├── entrypoint.c └── rust ├── Cargo.toml └── src └── lib.rs
いじるファイル src/rust: extendrを使ったRustのcrate。開発のメインはこ こ。
基本いじらないファイル Makevars, Makevars.win: パッケージインストール時に cargo build が走るように する設定。 entrypoint.c: コンパイラにシンボルを勝手に消されないためのおま
じない。 R/extendr-wrappers.R: Rustの関数から自動生成されたRの関数。 ` `
src/rust/Cargo.toml [package] name = 'myextendr' version = '0.1.0' edition =
'2018' [lib] crate-type = [ 'staticlib' ] [dependencies] extendr-api = '*'
src/rust/src/lib.rs(一部省略) use extendr_api::prelude::*; /// Return string `"Hello world!"` to R.
/// @export #[extendr] fn hello_world() -> &'static str { "Hello world!" } extendr_module! { mod myextendr; fn hello_world; }
src/rust/src/lib.rs よく使う関数をまとめて読み込み /// (3つ)のコメントはそのままRoxygenのコ メントになる これをつけるとRの関数が自動生成! use extendr_api::prelude::*; ` `
/// Return string `"Hello world!"` to R. /// @export #[extendr]
src/rust/src/lib.rs 関数をエクスポートしてRが認識できるように登録 (routine registration)してくれるマクロ。 新 しく関数を追加したらここに入れる必要がある。 extendr_module! { mod myextendr;
fn hello_world; }
開発の流れ
開発の流れ 1. Rustのコードを編集 2. rextendr::document() でRのコードを自動生成(Rust のコードのコンパイルもこれがやってくれる) 3. (必要あれば)生成されたコードをRの側でいい感 じにラップする
4. devtools::load_all() (やテスト)で動作確認 ` ` ` `
rextendr::document() ` ` > rextendr::document() ✓ Saving changes in the
open files. ℹ Generating extendr wrapper functions for package: myextendr. ! No library found at src/myextendr.so, recompilation is requi Re-compiling myextendr ─ installing *source* package ‘myextendr’ ... (382ms) ** using staged installation ** libs rm -Rf myextendr.so ./rust/target/release/libmyextendr.a en gcc -std=gnu99 -I"/usr/share/R/include" -DNDEBUG -fpic cargo build --lib --release --manifest-path=./rust/Cargo.to Updating crates.io index
生成されるファイル . ... ├── NAMESPACE <- @exportが反映される ├── R │
└── extendr-wrappers.R <- Rustの関数から自動生成 └── src ├── myextendr.so <- libmyextendr.aを使ってビルドされた └── rust 共有オブジェクト └── target <- Rustの生成物が入るディレクトリ └── release ├── libmyextendr.a <- Rustのコードの静的ライブラリ ... (OSによって拡張子は違う)
自動生成されたRの関数 Rust R /// Return string `"Hello world!"` to R.
/// @export #[extendr] fn hello_world() -> &'static str { "Hello world!" } #' Return string `"Hello world!"` to R. #' @export hello_world <- function() .Call(wrap__hello_world)
実行結果 #> [1] "Hello world!" devtools::load_all(".") hello_world()
例1) i32 (integer)を引数に取る 関数
自動生成されたRの関数 Rust R /// @export #[extendr] fn add(x: i32, y:
i32) -> i32 { x + y } #' @export add <- function(x, y) .Call(wrap__add, x, y)
実行結果 #> [1] 3 #> Error in add(1:2, 2:3) :
#> Input must be of length 1. Vector of length >1 given. devtools::load_all(".") # 引数の型は i32 だけど実数も渡せる add(1, 2) # 長さ1以上だとエラーになる add(1:2, 2:3)
例2) Vec<i32>を引数に取る関数
自動生成されたRの関数 Rust R #[extendr] fn mult(x: Vec<i32>, y: i32) ->
Vec<i32> { x .iter() .map(|n| n * y) .collect::<Vec<_>>() } #' @export mult <- function(x, y) .Call(wrap__mult, x, y)
実行結果 #> [1] 10 20 30 40 50 devtools::load_all(".") mult(1:5,
10)
例3) struct
struct…? 環境としてエクスポートされるので状態を持つこ とができる たまに便利(正規表現のキャッシュを持たせてい る例: rr4r)
自動生成されたRの関数 Rust struct Counter { i: i32, } /// @export
#[extendr] impl Counter { fn new() -> Self { Self { i: 0 } } fn count(&mut self) -> i32 { self.i = self.i + 1; self.i } }
自動生成されたRの関数 R #' @export Counter <- new.env(parent = emptyenv()) Counter$new
<- function() .Call(wrap__Counter__new) Counter$count <- function() .Call(wrap__Counter__count, self) #' @rdname Counter #' @usage NULL #' @export `$.Counter` <- function (self, name) { func <- Counter[[name]]
実行結果 #> [1] 1 #> [1] 2 devtools::load_all(".") cnt <-
Counter$new() cnt$count() cnt$count()
その他こまごました話 (時間があれば)
その他 文字列関連はlifetimeを意識しないと使えないの で初心者にはハードモード。数値計算系からはじ めるのがおすすめ。 Windowsのセットアップはやや面倒だけど、 GitHub Actionsでビルド済みのバイナリを配布し たりできるはず(調査中) CRANにはすでにextendrを使っているパッケージ も存在する
まとめ
まとめ extendrを使うとマクロの魔術でRustの関数から Rの関数を生成してくれる。 関数の引数の対応づけはRcppやcpp11と同じノ リ。慣れている人はわりとすぐに使えるはず。 ちなみに、今回はすべてRustのデータ型に変換 するタイプだったが、SEXPのまま扱うことも できる(ここはよく理解できていない) フィードバックお待ちしています!
r-wakalangにrustチャンネルをつくり ました
References extendr: https://github.com/extendr/extendr extendrのロゴはCC-BY-SA 4.0ライセンスで配布 されています: https://github.com/extendr/artwork.