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
ffi & native extension
Search
atomiyama
October 17, 2019
Programming
280
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ffi & native extension
heiseirb9
atomiyama
October 17, 2019
More Decks by atomiyama
See All by atomiyama
SchemaDrivenDevelopment
atomiyama
0
480
Rustでgemを作ろう
atomiyama
0
1.7k
技術選定で失敗したはなし
atomiyama
0
1.4k
はじめてのDocker
atomiyama
0
120
Other Decks in Programming
See All in Programming
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.6k
[Dev Group Paris Octobre 26] Agentforce, SIforce, Claudeforce, Slackbot… on s'y retrouve ?
nabondance
0
120
AmebaブログはKMPから卒業します
kmars0605
0
220
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
180
ChromeでローカルLLM
ryu1013
0
160
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
440
[2026-10-09]一枚の布で作らなくてもいい。 信頼性は「パッチワーク」で紡がれる~既存の運用と新しい可能性をつなぎ合わせてきたCREの話~
tosite
0
110
Seven New Principles of Software Engineering
yegor256
0
190
Web Framework Benchmark Battle 2026, Any%
a_matsuda
2
2.7k
re:Inventに行く前に知っておきたい現地参加のノウハウ
nokomoro3
0
450
AI-Powered Domain-Driven Design
ziobrando
0
210
Domain-Driven Transformation
hschwentner
2
2.3k
Featured
See All Featured
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
43k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.5k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
360
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
2
950
First, design no harm
axbom
PRO
2
1.3k
Faster Mobile Websites
deanohume
310
32k
Side Projects
sachag
456
43k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
310
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Navigating Weather and Climate Data
rabernat
0
560
A Soul's Torment
seathinner
8
3.8k
Transcript
FFI & Native Extension 1
github.com/atomiyama/heiseirb9 2
whoami Akifumi Tomiyama Studyplus Inc, H3.12.16 server-side enginner github: @atomiyama
Twitter: @atomiyama1216 3
好きな⾔語はなんですか? 4
Rust & Ruby 5
RubyからRustを呼んでみたい 6
why 早いらしい 低レイヤの⾔語書いてみたかった => それを好きなRubyから呼べたら楽しそう 7
Rubyから他の⾔語を呼び出す⽅法 FFI (Foreign Function Interface) Native Extension 8
FFI (foreign function interface) ⾊々な⾔語で定義された関数とかをRubyから呼べるようにしてくれる. => Rustなりから作成した共有ライブラリの関数シンボルとシグネチャーをRubyスクリプトか ら渡すことでRustの関数を呼び出せるように橋渡しをしてくれる. ただ引数の型, 戻り値の型といった関数シグネチャーの情報は与えてあげる必要があるので使
いたい数が増えればRuby側もそれなりの記述量になるしRustで書いてRubyでも書くってちょ っと違う. 9
Native Extension (拡張ライブラリ) Rubyからは普通のライブラリと同じようにrequireするたけで呼び出せる. => ruby-ffiでやっていたような橋渡しのような役割も記述する必要があって rb_define_method などのAPIを使ってRubyを拡張してあげる必要がある.こちらのほうが 圧倒的に記述量は多いように感じるけどRuby側から関数シグネチャー渡したりしなくてよい のいい.
10
こんにちは世界! Rustで適当に関数を定義 // hello_world.rs #[no_mangle] pub extern fn hello_world() {
println!("Hello World, I am Rust!"); } コンパイルしてdylibファイル⽣成 $ rustc --crate-type="dylib" hello_world.rs # 関数シンボルが存在するか確認する $ nm libhello_world.dylib | grep hello_world 0000000000000f10 T _hello_world 0000000000090b60 S _rust_metadata_hello_world_8787f43e282added376259c1adb08b80 11
ffiでrubyから関数を呼び出す require 'ffi' module RustEx extend FFI::Library ffi_lib "libhello_world.dylib" attach_function
:hello_world, [], :void end pp RustEx::hello_world #=> "Hello World, I am Rust!" 12
ほんとに早くなってるのか 13
Rust Tutorialにあるやつ 14
10個のスレッドで500万までカウントするコード threads = [] 10.times do threads << Thread.new do
count = 0 5_000_000.times do count += 1 end count end end threads.each do |t| puts "Thread finished with count=#{t.value}" end puts "done!" 15
Rustで書く(ffi) #![crate_type="dylib"] use std::thread; #[no_mangle] pub extern fn process() {
let handles: Vec<_> = (0..10).map(|_| { thread::spawn(|| { let mut x = 0; for _ in 0..5_000_000 { x += 1 } x }) }).collect(); for h in handles { h.join().unwrap(); }; } 16
Rubyから呼ぶ require 'ffi' module FFIEx extend FFI::Library ffi_lib './liblib.dylib' attach_function
:process, [], :void end pp FFIEx.process 17
計測してみる require "./ffi/main" require "./purerb/main" require "benchmark/ips" Benchmark.ips do |x|
x.report "Ruby Func" do PureRuby.process end x.report "Rust Func" do FFIEx.process end x.compare! end 18
早い!!! $ ruby benchmark.rb Warming up -------------------------------------- Ruby Func 1.000
i/100ms Rust Func 1.000 i/100ms Calculating ------------------------------------- Ruby Func 0.526 (± 0.0%) i/s - 3.000 in 5.709806s Rust Func 1.232 (± 0.0%) i/s - 7.000 in 5.684935s Comparison: Rust Func: 1.2 i/s Ruby Func: 0.5 i/s - 2.34x slower 19
Native Extension #![allow(non_snake_case)] extern crate libc; use std::ffi::CString; use std::thread;
type VALUE = libc::c_ulong; extern { fn rb_define_module(name: *const libc::c_char) -> VALUE; fn rb_define_module_function(module: VALUE, name: *const libc::c_char, value: extern fn(), argc: libc::c_int) -> libc::c_void; } extern fn rb_process() { let handles: Vec<_> = (0..10).map(|_| { thread::spawn(move || { let mut x = 0; for _ in 0..5_000_000 { x += 1 } x }) }).collect(); for h in handles { h.join().unwrap(); }; } #[no_mangle] // Init_{filename} の関数がエントリポイントになる // e.g. hoge.bundle をruby でrequire したらInit_hoge がエントリポイントになる pub extern fn Init_rustex() { let module_name = CString::new("RustEx").unwrap(); let process = CString::new("process").unwrap(); unsafe { let rb_cRustEx = rb_define_module(module_name.as_ptr()); rb_define_module_function(rb_cRustEx, process.as_ptr(), rb_process, 0); } } 20
呼ぶ # ./target/debug/librustex.dylib が作成される $ cargo build # macOS ではDynamic
Linking とDynamic Loading が明確に区別されていてruby からrequire するときはDynamic Loading が必要なので.bundle に変更しています $ mv target/debug/librustex.dylib rustex.bundle require "./rustex.bundle" RustEx.process 21
終わり 22