Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
RパッケージでRustを使うには: extendr入門 / extendr-pkg-dev
yutannihilation
May 30, 2021
Programming
1
3.7k
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
1
420
rayshader入門 / rayshader-tokyor88
yutannihilation
0
480
RとApache Arrow / r-and-apache-arrow
yutannihilation
4
3.6k
そろそろ使ってみませんかApache Arrow / why-dont-you-arrow-now
yutannihilation
1
490
A Graphical Introduction to tidyr's pivot_*()
yutannihilation
5
4.5k
tidyr 1.0.0の新機能 pivot_*() / tidyr-pivot
yutannihilation
4
8.2k
RとApache Arrow
yutannihilation
0
2.6k
Yet Another Introduction to tidyeval
yutannihilation
10
6.7k
Introduction to gghighlight
yutannihilation
6
2.5k
Other Decks in Programming
See All in Programming
LegalForceの契約データを脅かすリスクの排除と 開発速度の向上をどうやって両立したか
aibou
0
120
Hapticをカスタマイズしてみよう / ZOZO Tech Talk #6 Customize Haptic
endoumari
0
320
Kotlin 最新動向2022 #tfcon #techfeed
ntaro
1
1.1k
Get Ready for Jakarta EE 10
ivargrimstad
0
2.5k
Better Reliability through Observability (and Experimentation)
ksatirli
PRO
1
260
Go API クライアントの実装 〜Go Conference に載せれなかったTIPS〜
yyoshiki41
0
190
SPA/MPA 議論の俯瞰と 現代における設計のポイント - #tfcon 2022 フロントエンド設計
ahomu
3
1.8k
byte列のbit表現を得るencodingライブラリ作った
convto
1
150
Explore Java 17 and beyond
josepaumard
3
650
코드 품질 1% 올리기
pluu
1
980
Enterprise Angular: Frontend Moduliths with Nx and Standalone Components @jax2022
manfredsteyer
PRO
0
300
質とスピード(2022春版、質疑応答用資料付き) / Quality and Speed 2022 Spring Edition
twada
PRO
29
18k
Featured
See All Featured
Bootstrapping a Software Product
garrettdimon
295
110k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
15
910
Art Directing for the Web. Five minutes with CSS Template Areas
malarkey
196
9.4k
The Pragmatic Product Professional
lauravandoore
19
2.9k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
350
21k
Optimizing for Happiness
mojombo
365
63k
The Language of Interfaces
destraynor
148
20k
What's new in Ruby 2.0
geeforr
336
30k
A Modern Web Designer's Workflow
chriscoyier
689
180k
The MySQL Ecosystem @ GitHub 2015
samlambert
238
11k
JazzCon 2018 Closing Keynote - Leadership for the Reluctant Leader
reverentgeek
172
8.3k
Scaling GitHub
holman
451
140k
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.