すがブロ

sugamasaoのhatenablogだよ

rustでgemパッケージ内のコードを書く方法のメモ

Ruby 3.2に同梱されるBundlerでは、 bundle gem--ext=rust とすることでrustでgemのコードを書けるようになります。

新しいものはとりあえず触ってみたいので、試してみましょう(完全にn番煎じなのですが、自分用の備忘録です)

事前準備

  • rustのビルド環境
  • Ruby 3.2.0(正確にはBubdler 2.4.0以上)

やってみる

rust_gem_sample という名前のライブラリを作ってみるとしましょう。

$ bundle gem rust_gem_sample --ext=rust
 : # 場合によってはさまざまな質問があるので適当に答える

これで雛形ができる。 作成された rust_gem_sample ディレクトリへ移動し、コードをさらっと眺めてみましょう。

rustのコードはC言語の場合と同じように ext ディレクトリ内に生成される。

$ tree ext
ext
└── rust_gem_sample
    ├── Cargo.toml
    ├── extconf.rb
    └── src
        └── lib.rs

ちなみに、生成されるサンプルコードはこんな感じ

# ext/rust_gem_sample/src/lib.rs
use magnus::{define_module, function, prelude::*, Error};

fn hello(subject: String) -> String {
    format!("Hello from Rust, {}!", subject)
}

#[magnus::init]
fn init() -> Result<(), Error> {
    let module = define_module("RustGemSample")?;
    module.define_singleton_method("hello", function!(hello, 1))?;
    Ok(())
}

define_singleton_method でメソッドが定義されているということは、RustGemSample.hello で呼び出せて、1つの引数を受け取るコードってことですね。

さて、ビルドするためには事前準備が必要なので、以下を修正します(これはrust関係なく、bundle gemした時に必要な一般的なもの)。

  • rust_gem_sample.gemspec
    • TODOをURLっぽい値に書き換えておく(これをしないとビルド時にエラーになる)
  • testを生成している場合、自動生成された test コード
    • デフォルトのコードは失敗するようなコードになっているので、修正するなり消すなりする必要がある

これは余談ですが、久しぶりにgemspecの中身を見て source_code_urichangelog_uri というのが設定できるということを知りました。RubyGemsのドキュメントを見るに、設定しておくとrubygems.orgのサイドバーにいい感じに表示してくれるっぽいですね……?

$ ./bin/setup
$ bundle exec rake

これで無事にビルドできるはずです。

ではお試しで実行してみましょう。

$ ./bin/console
Ignoring rust_gem_sample-0.1.0 because its extensions are not built. Try: gem pristine rust_gem_sample --version 0.1.0
irb(main):001:0> RustGemSample.hello("hoge")
=> "Hello from Rust, hoge!"
irb(main):002:0>

おー、うごいた!

せっかくなのでブログにしてみよーと思って書き始めたのですが、なんか、思ったより何もせず動いてしまった……(いい話)。