8
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?

ElixirAdvent Calendar 2024

Day 13

Livebook で Rust を実行する

Last updated at Posted at 2024-12-27

はじめに

効率的で信頼できるソフトウェアを誰もがつくれる言語

引用元

Rustler を使うことで、 Elixir から Rust のコードを呼べるようになります

本来であれば mix new で作った Elixir のプロジェクト内で使用するものですが、無理矢理 Livebook で動かしました

Livebook では Rustler 経由での Rust のビルドができなかったため、 Rustler 内部で行なっていることを Livebook で実行しています

ちゃんと Rustler を使っている例は @pojiro さんの記事をご覧ください

https://qiita.com/pojiro/items/a105021cce44ca4ff282

本記事では Livebook で(一部) Rustler を使い、 Rust のコードを実行します

実装したコードはこちら

前提条件

実行環境には Rust をインストールしておきます

セットアップ

セットアップセルで Rustler をインストールします

Mix.install([
  {:rustler, "~> 0.35.1"}
])

Rust プロジェクトの生成

Rustler を使って Rust のプロジェクトを生成します(cargo new と同じようなこと)

そのまま実行すると Livebook 実行環境のホームディレクトリーに作られてしまうため、 /tmp に移動します

File.cd("/tmp")

Elixir 側のモジュール名 module と Rust 側のプロジェクト名 name を定義しておきます

module = "LearnRustler.Nif"
name = "learn_rustler_nif"

Rust のプロジェクトを作成します

Mix.Tasks.Rustler.New.run(["--module", module, "--name", name])

上記のコードは mix rustler.new --module LearnRustler.Nif --name learn_rustler_nif を実行したのと同じことになります

標準出力には以下のように表示されます

* creating native/learn_rustler_nif/.cargo/config.toml
* creating native/learn_rustler_nif/README.md
* creating native/learn_rustler_nif/Cargo.toml
* creating native/learn_rustler_nif/src/lib.rs
* creating native/learn_rustler_nif/.gitignore
Ready to go! See /tmp/native/learn_rustler_nif/README.md for further instructions.

生成されたプロジェクトのパス native_path と、その中の src/lib.rs のパス src_path を定義しておきます

native_path = Path.join([File.cwd!(), "native", name])
src_path = Path.join([native_path, "src", "lib.rs"])

src/lib.rs の中身を実装したい内容に書き換えます

今回は加算、乗算、ソート、挨拶の関数を Rust で実装しました

File.write!(src_path,"""
#[rustler::nif]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[rustler::nif]
fn multiply(a: i32, b: i32) -> i32 {
    a * b
}

#[rustler::nif]
fn sort(v: Vec<i32>) -> Vec<i32> {
    let mut sorted = v;
    sorted.sort();
    sorted
}

#[rustler::nif]
fn hello(name: &str) -> String {
    format!("Hello, {}", name)
}

rustler::init!("Elixir.LearnRustler.Nif");
""")

Rust プロジェクトのビルド

cargo rustc --release を実行し、 Rust プロジェクトをビルドします

System.cmd(
  "cargo",
  ["rustc", "--release"],
  cd: native_path,
  stderr_to_stdout: true,
  into: IO.stream(:stdio, :line)
)

標準出力

   Compiling proc-macro2 v1.0.92
   Compiling unicode-ident v1.0.14
   Compiling regex-lite v0.1.6
   Compiling heck v0.5.0
   Compiling cfg-if v1.0.0
   Compiling inventory v0.3.16
   Compiling libloading v0.8.6
   Compiling rustler v0.35.1
   Compiling quote v1.0.38
   Compiling syn v2.0.92
   Compiling rustler_codegen v0.35.1
   Compiling learn_rustler_nif v0.1.0 (/tmp/native/learn_rustler_nif)
    Finished `release` profile [optimized] target(s) in 8.39s

ビルドして作成された liblearn_rustler_nif.so のパスを定義しておきます

lib_path = Path.join([native_path, "target", "release", "liblearn_rustler_nif"])

NIF の読込

Elixir 側のモジュールを定義し、 load 関数で NIF を読み込みます

defmodule LearnRustler.Nif do
  def load(path), do: :erlang.load_nif(path, 0)

  def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded)
  def multiply(_a, _b), do: :erlang.nif_error(:nif_not_loaded)
  def sort(_v), do: :erlang.nif_error(:nif_not_loaded)
  def hello(_name), do: :erlang.nif_error(:nif_not_loaded)
end
LearnRustler.Nif.load(lib_path)

関数の実行

定義した関数を実行します

LearnRustler.Nif.add(3, 4)

実行結果

7
LearnRustler.Nif.multiply(3, 4)

実行結果

12
LearnRustler.Nif.sort([8, 5, 6, 2])

実行結果

[2, 5, 6, 8]
LearnRustler.Nif.hello("Rust")

実行結果

"Hello, Rust"

全て想定通りに動きました

まとめ

Livebook 上で Rust のコードを実行できました

本来、 Rustler を使う場合は以下のうようなモジュールを定義しておくだけで良いのですが、 Livebook の場合は :otp_app に指定するアプリケーション名が存在しないため、この方法は諦めました

defmodule LearnRustler.Nif do
  use Rustler, otp_app: :learn_rustler, crate: "learn_rustler_nif"

  def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded)
end

そのおかげで Rustler の中身を見て内容を理解できたので、むしろ良かったと思います

8
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
8
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?