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
Introduction to C Extensions
Search
sylph01
March 09, 2025
Programming
320
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Introduction to C Extensions
@ kyoto.rb 2025/3/9
sylph01
March 09, 2025
More Decks by sylph01
See All by sylph01
人命を救う技術としてのEnd-to-End暗号化とMessaging Layer Security
sylph01
3
260
Updates on MLS on Ruby (and maybe more)
sylph01
1
310
End-to-End Encryption Saves Lives. You Can Start Saving Lives With Ruby, Too (RubyConf Taiwan 2025 ver.)
sylph01
1
180
PicoRuby's Networking is Incomplete
sylph01
1
320
The Definitive? Guide To Locally Organizing RubyKaigi
sylph01
9
4.1k
End-to-End Encryption Saves Lives. You Can Start Saving Lives With Ruby, Too
sylph01
1
240
End-to-End Encryption Saves Lives. You Can Start Saving Lives With Ruby, Too (JP subtitles)
sylph01
2
1k
"Actual" Security in Microcontroller Ruby!?
sylph01
0
260
Everyone Now Understands AuthZ/AuthN and Encryption Perfectly and I'm Gonna Lose My Job
sylph01
1
150
Other Decks in Programming
See All in Programming
新卒PdEのリアル
ryu1013
1
500
Heart of Swift Concurrency
koher
0
730
ゲームコントローラやキーボードのファームウェアをSwiftで書く
kishikawakatsumi
1
240
Jetpack Compose メカニズム
skydoves
0
420
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
0
150
AIエージェント時代のコードレビューを設計する
nogu66
6
2.7k
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
280
アクセシビリティから考える情報設計
high_g_engineer
0
370
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
1
150
個人開発基盤をまるごとCloudflareに引っ越して爆速で総合的体験を向上させた話
tinykitten
0
190
MVNOの申込からeSIM開通までをiOSアプリでつなぐ- 本人確認・MNP・通信事業者基盤をまたぐ実装
satotakeshi
0
400
iOSDC2026登壇資料.pdf
riofujimon
0
160
Featured
See All Featured
The untapped power of vector embeddings
frankvandijk
2
1.9k
Utilizing Notion as your number one productivity tool
mfonobong
4
590
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
670
Building AI with AI
inesmontani
PRO
1
1.2k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Between Models and Reality
mayunak
4
460
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
Mind Mapping
helmedeiros
1
360
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
450
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
First, design no harm
axbom
PRO
2
1.3k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
570
Transcript
Introduction to C Extensions Ryo Kajiwara (sylph01), 2025/3/9 @ kyoto.rb
1
RubyKaigi, more like CKaigi, huh? よく冗談めかして言われますね 2
C 拡張って何 C 言語でRuby の機能を書くこと gem の形で使うことが多い C やアセンブリで書いたほうが速い部分をC で書く
実はJIT のおかげで必ずしもC だから速いというわけでもない C 以外の言語の入り口になることもある そういえば今年Go gem の話がありますね? 3
現代RubyKaigi ではもはやC 拡張の話は 当たり前のこととして通過される RubyKaigi のトークには新規性が必要(なことが多い) Ruby Core としてはもはや当たり前のもの C
で書かれたライブラリのラッパーだけでは新規性がない とはいえスルーするにはあまりにも不親切。なので今回できる限りの解 説を試みる。全部は 私もわからないので 解説しきれません。 4
見るべき2 大ドキュメント ruby/ruby のdoc/extension.rdoc 日本語がある(リンクは日本語のほう) The Definitive Guide to Ruby's
C API 5
実際に自分が手を入れた/ ているコー ドがこちら https:/ /github.com/sylph01/openssl/blob/hpke/ext/openssl/ossl_hpke _ctx.c https:/ /github.com/sylph01/openssl/blob/hpke/ext/openssl/ossl_ hpke_ctx.h https:/
/github.com/sylph01/openssl/blob/hpke/ext/openssl/ossl.c から Init_ossl_hpke_ctx() が呼ばれるのがエントリーポイ ント 6
クラス/ モジュールの定義 void Init_ossl_hpke_ctx(void) { mHPKE = rb_define_module_under(mOSSL, "HPKE"); cContext
= rb_define_class_under(mHPKE, "Context", rb_cObject); cSenderContext = rb_define_class_under(cContext, "Sender", cContext); cReceiverContext = rb_define_class_under(cContext, "Receiver", cContext); eHPKEError = rb_define_class_under(mHPKE, "HPKEError", eOSSLError); ... class OpenSSL::HPKE::Context class OpenSSL::HPKE::Context::Sender class OpenSSL::HPKE::Context::Receiver class OpenSSL::HPKE::Error 7
メソッドの定義 rb_define_method(cSenderContext, "initialize", ossl_hpke_ctx_new_sender, 2); (1) 定義したいクラス、(2) メソッド名、(3) 実装を示す関数ポインタ、(4) 引数の個数
以下に相当 class OpenSSL::HPKE::Context::Sender def initialize(arg1, arg2) end 8
メソッドの定義 VALUE ossl_hpke_ctx_new_sender(VALUE self, VALUE mode, VALUE suite) { ...
C の世界ではRuby のオブジェクトは全部 VALUE 自身がどんな型であるかを知っているデータ(へのポインタ) (1) self 、(2) 以降は rb_define_method で指定した引数の数だけ VALUE が続く return で返す VALUE がRuby の世界で返る値 9
メソッドの定義 おまけ: モジュール関数の場合は rb_define_module_function rb_define_module_function(mHPKE, "keygen", ossl_hpke_keygen, 3); おまけ2: mruby/c
ではどうするの?→るびま0064 号のRubyKaigi 2024 の トーク解説記事 10
attributes // attr_readers for suite values rb_define_attr(cContext, "kem_id", 1, 0);
rb_define_attr(cContext, "kdf_id", 1, 0); rb_define_attr(cContext, "aead_id", 1, 0); https:/ /docs.ruby-lang.org/ja/latest/function/rb_define_attr.html 第3 引数はread 、第4 引数はwrite 11
インスタンス変数 rb_iv_set(self, "@kem_id", kem_id); kem_id = rb_iv_get(suite, "@kem_id"); get するときは
VALUE が返ってくるので、Ruby の世界のinteger をC で使 う場合は NUM2INT(kem_id) みたいな形で変換する。 12
定数の呼び出し https:/ /docs.ruby-lang.org/ja/latest/function/rb_const_get_at.html による と VALUE rb_const_get_at(VALUE klass, ID name)
。 ID → rb_intern で名前との対応関係が得られる。 mode_table = rb_const_get_at(cContext, rb_intern("MODES")); 13
Ruby の世界の関数を呼び出す mode_id = rb_funcall(mode_table, rb_intern("[]"), 1, mode); ↓ mode_id
= MODES[mode] rb_p(rb_funcall(rbstr, rb_intern("unpack1"), 1, rb_str_new_cstr("H*"))); ↓ p(str.unpack1("H*")) 14
C の構造体をRuby で包む static void ossl_hpke_ctx_free(void *ptr) { OSSL_HPKE_CTX_free(ptr); }
const rb_data_type_t ossl_hpke_ctx_type = { "OpenSSL/HPKE_CTX", { 0, ossl_hpke_ctx_free, }, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; 15
C の構造体をRuby で包む static VALUE hpke_ctx_new0(VALUE arg){ OSSL_HPKE_CTX *ctx =
(OSSL_HPKE_CTX *)arg; VALUE obj; obj = rb_obj_alloc(cContext); RTYPEDDATA_DATA(obj) = ctx; return obj; } VALUE ossl_hpke_ctx_new(OSSL_HPKE_CTX *ctx){ VALUE obj; int status; obj = rb_protect(hpke_ctx_new0, (VALUE)ctx, &status); if (status) { OSSL_HPKE_CTX_free(ctx); rb_jump_tag(status); } return obj; 16
C の構造体をRuby で包む static VALUE ossl_hpke_ctx_alloc(VALUE klass) { return TypedData_Wrap_Struct(klass,
&ossl_hpke_ctx_type, NULL); } void Init_ossl_hpke_ctx(void) { mHPKE = rb_define_module_under(mOSSL, "HPKE"); cContext = rb_define_class_under(mHPKE, "Context", rb_cObject); ... rb_define_alloc_func(cContext, ossl_hpke_ctx_alloc); } 17
C 拡張ってどうやってビルドするの? https:/ /docs.ruby-lang.org/ja/latest/library/mkmf.html Makefile を生成するためのライブラリ。 extconf.rb からmkmf をrequire してMakefile
が作られてshared object が作ら れる。 皆さんももしかしたら apt-get し足りない何かがあったときに extconf.rb がfailed になってるのを見たことあるかもしれない。 18
おまけ: Copilot に作らせてみた だいたい https:/ /github.com/tilo/gem_with_c_extension と近い内容のも のが出てきたが、Mac でビルドできなかった。shared object
( .so ) ファ イルが作られなかった 19
ext/my_c_extension/extconf.rb require 'mkmf' create_makefile('my_c_extension/my_c_extension') 20
ext/my_c_extension/my_c_extension.c #include "ruby.h" VALUE rb_mMyCExtension; VALUE hello_world(VALUE self) { return
rb_str_new_cstr("Hello, world!"); } void Init_my_c_extension() { rb_mMyCExtension = rb_define_module("MyCExtension"); rb_define_method(rb_mMyCExtension, "hello_world", hello_world, 0); } 21
gemspec Gem::Specification.new do |spec| # ... other configurations ... spec.extensions
= ['ext/my_c_extension/extconf.rb'] spec.files = Dir.chdir(File.expand_path(__dir__)) do `git ls-files -z`.split("\x0").select do |f| f.match(%r{^(ext|lib)/}) || f == 'my_c_extension.gemspec' end end # ... other configurations ... end 22
Ruby ラッパー require 'my_c_extension/my_c_extension' module MyCExtension def self.hello MyCExtension.hello_world end
end 23