2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rubyのネイティブ拡張をRustで作成する最小構成(今の所Macのみ)

Last updated at Posted at 2020-12-13

現在、RustでRubyのネイティブ拡張を書く場合、rutieを使うことが一般的だと思われる。(helixruruは保守されていない。)
しかし、下記の理由で個人的に好ましくなかったため、ライブラリに頼らずRubyのネイティブ拡張を作る方法を調べた。

  • 古いRustコンパイラをサポートするが、MaybeUninit等の、より安全なライブラリが利用されていない。
  • unsafeに対する価値観が私と異なり、完全に安全とは言えない関数であってもunsafeとマークされていない。

下記のコードは HelloRust モジュールをRust側で定義しているサンプルである。

Windows, Linux で動かす場合は続きを参考。

ソースコードベタ貼り

run.rb
require __dir__ + "/hello_rust"

if defined?(HelloRust)
  puts "HelloRust is defined"
else
  puts "HelloRust is not defined"
end
src/lib.rs
use std::ffi;

#[repr(transparent)]
pub struct Value(usize);

#[link(name = "ruby")]
extern "C" {
  fn rb_define_module(name: *const i8) -> Value;
}

fn define_module(name: &ffi::CStr) -> Value {
  unsafe { rb_define_module(name.as_ptr()) }
}

#[export_name = "Init_hello_rust"]
pub extern "C" fn init() {
  let s = ffi::CString::new("HelloRust").unwrap();
  define_module(&s);
}
build.rs
use std::process::Command;

fn libdir() -> String {
  let output = Command::new("ruby")
    .args(&["-e", "print RbConfig::CONFIG['libdir']"])
    .output()
    .expect("failed run ruby");

  return String::from_utf8(output.stdout).unwrap();
}

fn main() {
  println!("cargo:rustc-link-search={}", libdir());
}
Cargo.toml
[package]
name = "hello_rust"
version = "0.1.0"
authors = ["irxground"]
edition = "2018"

[lib]
crate-type = ["cdylib"]
Makefile
.PHONY: build
build: hello_rust.bundle

hello_rust.bundle: cargo_build
	cp -a target/release/libhello_rust.dylib $@

.PHONY: cargo_build
cargo_build:
	cargo build --release

.PHONY: run
run: clean build
	ruby run.rb

.PHONY: clean
clean:
	rm *.bundle
	cargo clean

実行結果

$ make run
rm *.bundle
cargo clean
cargo build --release
   Compiling hello_rust v0.1.0 (/Users/user/work/private/ruby_rust/minimam_rust_example)
    Finished release [optimized] target(s) in 0.75s
cp target/release/libhello_rust.dylib hello_rust.bundle
ruby run.rb
HelloRust is defined
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?