Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RパッケージでRustを使うには: extendr入門 / extendr-pkg-dev
Search
yutannihilation
May 30, 2021
Programming
1
6.3k
RパッケージでRustを使うには: extendr入門 / extendr-pkg-dev
第92回R勉強会
の発表スライドです。
(
ウェブ版
をPDFエクスポートしたものですが、Slidevの使い方がわからず画像が消えてしまっています...)
yutannihilation
May 30, 2021
Tweet
Share
More Decks by yutannihilation
See All by yutannihilation
🦀
yutannihilation
2
700
rayshader入門 / rayshader-tokyor88
yutannihilation
0
980
RとApache Arrow / r-and-apache-arrow
yutannihilation
4
6.6k
そろそろ使ってみませんかApache Arrow / why-dont-you-arrow-now
yutannihilation
1
990
A Graphical Introduction to tidyr's pivot_*()
yutannihilation
5
5.1k
tidyr 1.0.0の新機能 pivot_*() / tidyr-pivot
yutannihilation
4
10k
RとApache Arrow
yutannihilation
0
3.2k
Yet Another Introduction to tidyeval
yutannihilation
10
7.6k
Introduction to gghighlight
yutannihilation
6
2.8k
Other Decks in Programming
See All in Programming
2024/11/8 関西Kaggler会 2024 #3 / Kaggle Kernel で Gemma 2 × vLLM を動かす。
kohecchi
5
970
Welcome JSConf.jp 2024
yosuke_furukawa
PRO
0
380
Contemporary Test Cases
maaretp
0
140
「今のプロジェクトいろいろ大変なんですよ、app/services とかもあって……」/After Kaigi on Rails 2024 LT Night
junk0612
5
2.2k
Jakarta EE meets AI
ivargrimstad
0
290
聞き手から登壇者へ: RubyKaigi2024 LTでの初挑戦が 教えてくれた、可能性の星
mikik0
1
140
Amazon Qを使ってIaCを触ろう!
maruto
0
420
watsonx.ai Dojo #4 生成AIを使ったアプリ開発、応用編
oniak3ibm
PRO
1
220
WebフロントエンドにおけるGraphQL(あるいはバックエンドのAPI)との向き合い方 / #241106_plk_frontend
izumin5210
4
1.4k
Jakarta EE meets AI
ivargrimstad
0
810
Jakarta EE meets AI
ivargrimstad
0
370
ふかぼれ!CSSセレクターモジュール / Fukabore! CSS Selectors Module
petamoriken
0
150
Featured
See All Featured
KATA
mclloyd
29
14k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.7k
Art, The Web, and Tiny UX
lynnandtonic
297
20k
Testing 201, or: Great Expectations
jmmastey
38
7.1k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
How STYLIGHT went responsive
nonsquared
95
5.2k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Navigating Team Friction
lara
183
14k
The World Runs on Bad Software
bkeepers
PRO
65
11k
Designing for Performance
lara
604
68k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.1k
Building a Scalable Design System with Sketch
lauravandoore
459
33k
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.