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
Rust で作ったネイティブを Ruby から使う
Search
yo_waka
August 26, 2026
Technology
64
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Rust で作ったネイティブを Ruby から使う
2026/08/26 gotanda.rb での発表資料です
yo_waka
August 26, 2026
More Decks by yo_waka
See All by yo_waka
うちの技術負債2021_freee会計編
waka
0
1.2k
大きなプロダクトの育て方
waka
10
27k
requireの循環参照
waka
0
1.5k
Other Decks in Technology
See All in Technology
DGX Sparkを2台使って いろいろ動かす話
sonoda_mj
1
120
Kiro Crewしか勝たん!?
miu_crescent
PRO
0
170
Driving AI Adoption Using In-House GPUs to Serve Qwen
po3rin
2
410
AIエージェントの開発・提供におけるセキュリティリスクの論点と対策
flatt_security
1
520
少人数データチームのDevin活用実践事例
runandy16
2
430
V8コントリビュート超入門
riyaamemiya
0
130
Jetpack Compose で挑む新聞紙面UI ─ 複合ジェスチャー・ポリゴン記事領域・適応的ページ構成という3つの壁/droidkaigi2026
nikkei_engineer_recruiting
0
170
KAEN Company Deck
kaen
PRO
0
290
「重なり」は迎える側がつくる ― 人もAIエージェントも歓迎するプロダクトエンジニアリング ―
go0517go
PRO
0
210
作り直せるコードは迅速に 作り直せないDBは慎重に - AI時代のプロダクトエンジニアが「判断の不可逆性」で開発速度を変える話
kinosuke01
0
170
Claude Codeの体系的な理解と知識のフック
oikon48
10
6.6k
2026-09-04 SRE Tech Talk #15 怠惰なTerraform / Lazy Terraform
masasuzu
0
170
Featured
See All Featured
Darren the Foodie - Storyboard
khoart
PRO
3
3.9k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
490
The Pragmatic Product Professional
lauravandoore
37
7.4k
Prompt Engineering for Job Search
mfonobong
0
430
GitHub's CSS Performance
jonrohan
1033
470k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Crafting Experiences
bethany
1
280
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
450
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
69
65k
Testing 201, or: Great Expectations
jmmastey
46
8.3k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
Transcript
Rust製のネイティブビルド をRubyから使う 2026.08.26 ∕ gotanda.rb 1
はじめまして • @yo_waka • 匠のあそびという会社で Ruby / Rails をやっています •
PDF が好きです 2
HTML to PDF をやるやつを作っています • https://github.com/waka/sghtmltopdf • wkhtmltopdf という QtWebkit
を組み込んだ HTML を PDF に変換するプログラムと、 それを ActionView の DSL から使える wicked_pdf という gemを使っていた • wkhtmltopdf は QtWebkit のバージョンアップに追随できず、2023 年に残念ながらアーカイブされてし まった • ⾃分は ActionView の DSL で PDF を出⼒できるというのがとても気に⼊っていたので、より⾼速で使い勝 ⼿を⾼めたものを作ろうと思った 3
Rust製 のネイティブビルドを Ruby から使いたい • sghtmltopdf は HTML to PDF
をやるためのライブラリが優秀だったため、 Rust で書かれている ◦ HTML/CSS のパースは Servo プロジェクト(※) が提供している crate を活⽤ ▪ • html5ever, css-parser ◦ PDF の書き出しは pdf-writer crate を活⽤ ◦ パース結果を PDF の レイアウトに変換するエンジンやフォント表⽰周りが⾃作部分 wicked_pdf 同様に Ruby から使えるようにしたい = Rust のネイティブビルドを呼び出す必要がある ※ Mozilla 製の Firefox の HTML/CSS レンダリングエンジン。今は Linux Foundation に移管されている 4
Rust で Ruby のネイティブ拡張を書くためのライブラリ その1 rb-sys • Ruby C API
の⽣バインディング + ビルド基盤を提供 ◦ Ruby オブジェクトへの参照を表す型として VALUE が提供される ▪ 実体はポインタ幅の符号なし整数(詳細は次の次のページ) • bindgen で⽣成した 「rb_sys::rb_funcall」など⽣の関数‧型定義を提供 • 「rb_sys/mkmf」を提供して、extconf.rb から Cargo プロジェクトをビルド可能にする ◦ mkmf = make makefile ◦ gem インストール時に RubyGems が拡張ディレクトリの extconf.rb を実⾏する ◦ create_rust_makefile で cargo build して .so ファイルを作る ◦ .so ファイルを Ruby から読めるディレクトリに配置する Makefile を作成して Rubygems が make する 5
Rust で Ruby のネイティブ拡張を書くためのライブラリ その2 magnus • rb-sys を抽象化して、いい感じに使えるようにしてくれるライブラリ ◦
• Rust の型と Ruby の型の⾃動変換 ◦ • 「RString」「RArray」「RHash」「Symbol」など型付きの Ruby オブジェクトとして扱える fn(u64) -> String みたいな関数をそのまま Ruby 側のメソッドとして登録できる #[magnus::wrap] マクロで Rust の struct をRuby オブジェクトとして公開できたり 6
rb-sys と magnus の関係 • rb-sys が提供する VALUE とは ◦
◦ • pub type VALUE = usize; で定義される ▪ 下位 1bit が 1 => Fixnum ▪ 下位 8bit が 0x0e => Symbol ▪ 0x08 => nil 型システムの助けが⼀切なくなるので、このまま扱うのはきつい>< ▪ let a: VALUE = /* String */ ▪ let b: VALUE = /* Array */ ▪ let c = a + b; // これはコンパイル通るけど実⾏時に Segfault になる この VALUE を型付きで扱えるようにしてくれるのが magnus ◦ RString / RArray などの型で扱えるようにしてくれる ◦ rb-sys に直接渡せるように、 ⽣のVALUE を取り出す as_rb_value() も使える 7
Global VM Lock(GVL)に注意 • GVL = 1 プロセス内で Ruby のコードを実⾏できるスレッドを常に
1 つに制限するロック ◦ • Webアプリのようなマルチスレッド環境だと他のスレッドが⽌まっちゃう 普段意識することはあまりない ◦ IO#read / write, Socket 等の標準 IO は Ruby 内で GVL を⾃動で解放してくれる ◦ pg gem, mysql2 gem なんかは 内部で「rb_thread_call_without_gvl 」という GVL 解放メソッドを 呼んでGVL を解放してくれている • C 拡張や ネイティブを呼び出す、且つ IO が絡む gem を作る場合は自分で意識しないといけない 8
GVL を外さないとこうなる • 例えば、Puma をマルチスレッドで動かしていると、巨⼤な HTML が投げられると PDF 変換している間、他の スレッドが全部待ちになる
9
magnus (rb-sys)でGVLを外す場合 • magnus は GVL 解放する API を提供していない •
⾃前で「rb_thread_call_without_gvl 」を呼ぶしかない ◦ デザインパターンみたいなのがある ◦ 多分 => の実装にだいたいなるはず ◦ 気になる⼈は sghtmltopdf のリポジトリ⾒てみて ください! 10
Ruby <-> Rust の⼝はシンプルにしよう • GVL 解放している境界は分かりやすくした⽅がいい ◦ 解放前: Ruby
オブジェクトを Rust オブジェクトに変換 ◦ 解放後: Rust オブジェクトしか触らない ▪ ◦ 型で Rust オブジェクトのみ制限できる安心感 右のコード例では Ruby からは RStringを 受け取り、Rust の Vec に変換して、gvl 解放している • ↑ によって GC の影響をほぼ意識しなくてよくなります ◦ Ruby オブジェクトを持っちゃうと、 GC で棄てられるリスクがある 11
Rust で Rubygem、ツールが揃っていて 書きやすいのでおすすめです! 12