When using Rust NIFs in Elixir via the Rustler crate, it's often useful to pass structured data, not just integers and strings. This post shows how to pass an Elixir struct to Rust, manipulate it, and return a new struct to Elixir.
Define a struct in Elixir
Start by creating a simple struct, such as User:
defmodule MyNif.User do
defstruct [:name, :age]
end
Define the same struct in Rust
In your NIF crate (native/my_nif/src/lib.rs), define a matching Rust struct using Rustler's NifStruct derive macro:
use rustler::NifStruct;
#[derive(NifStruct)]
#[module = "MyNif.User"]
struct User {
name: String,
age: u32,
}
The #[module = "MyNif.User"] attribute tells Rustler how to map the Elixir struct to the Rust struct.
Write a NIF function that uses the struct
Here's a Rust NIF that increases a user's age:
#[rustler::nif]
fn birthday(user: User) -> User {
User {
age: user.age + 1,
..user
}
}
Register the function:
rustler::init!("Elixir.MyNif");
Wire it up in Elixir
In your wrapper module:
defmodule MyNif do
use Rustler, otp_app: :my_nif_app, crate: "my_nif"
def birthday(_user), do: :erlang.nif_error(:nif_not_loaded)
end
Call it from IEx
$ iex -S mix
iex> user = %MyNif.User{name: "Alice", age: 29}
iex> MyNif.birthday(user)
%MyNif.User{name: "Alice", age: 30}
Notes
- Fields must match exactly between Elixir and Rust.
- Rustler will raise a badarg error if field names or types don't match.
NifStructautomatically handles encoding and decoding usingserde.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.