Developing Erlang NIF using rust language

Time:2021-11-29

Rustler project is not very mature and basically available. If you are interested, you can provide the author with issue

Rustler is a secure library for writing Erlang NIF with rust. The meaning of security here is that it will not cause the crash of beam (Erlang virtual machine). The library provides a facility for generating templates for interacting with beam and processing the encoding and decoding of Erlang term. Rustler is applicable to Erlang and elixir, and elixir is preferred

function

  • Security – NIF written in rust will never cause beam to crash

  • Interoperability – encoding and decoding rust values to Erlang term is as easy as calling functions

  • Compound type – you can specify a rust structure as encoded and decodable with attributes

  • Resource object – you can safely pass the rust structure to Erlang code and automatically delete it when it is no longer referenced

introduction

The easiest way to get started is to use the mix project generator

Run the following command to install rustler’s mix project generator

mix archive.install https://github.com/hansihe/rustler_archives/raw/master/rustler_installer.ez

Run the following command to create a rustler project

mix rustler.new

You need to install the nightly version of rust. Install it firstrustup. and execute under the project directoryrustup override add nightly-2016-05-07-x86_64-apple-darwin.

Rust NIF

The following is a minimum rust NIF implementation, which simply implements an addition function to return the sum of two numbers

#![feature(plugin)]
#![plugin(rustler_codegen)]

#![feature(link_args)]
#[link_args = "-flat_namespace -undefined suppress"]
extern {}

#[macro_use]
extern crate rustler;
use rustler::{ NifEnv, NifTerm, NifResult, NifEncoder };

rustler_export_nifs!(
    "Elixir.Test",
    [("add", 2, add)],
    None
);

fn add<'a>(env: &'a NifEnv, args: &Vec<NifTerm>) -> NifResult<NifTerm<'a>> {
    let num1: i64 = try!(args[0].decode());
    let num2: i64 = try!(args[1].decode());
    Ok((num1 + num2).encode(env))
}

Reference to compilation problems under OSXhttps://github.com/hansihe/Ru…

Integration with mix project

For projects using mix, there is one on hexAssistant packageThis package contains a mix compiler for automatic environment checking, crite compilation and NIF loading. If you use mix, this package is highly recommended, which makes it more convenient for you to develop Erlang NIF based on rust

To start automatic compilation with rust NIF, complete the following steps:

  • add torustlerDependency to mix.exs

  • Add: rustler compiler to projectcompilersListcompilers: [:rustler] ++ Mix.compilers

  • Add arustler_crates: ["CRATE_PATH"]reachprojectFunction,CRATE_PATHShould be a to includeCargo.tomlThe relative path of the file relative to the mix project directory

After completionmix.exsThe file looks like this:

defmodule YourProject.Mixfile do
  use Mix.Project
 
  def project do
    [app: :your_project,
     [...]
     compilers: [:rustler] ++ Mix.compilers,
     rustler_crates: ["."],
     deps: deps]
  end

  [...]
 
  defp deps do
    [{:rustler, "~> 0.0.7"}]
  end
end

Then you can passmix compileCompile the project. If there is any problem with the environment settings, the rustler compiler plug-in should be able to prompt relevant instructions on how to solve it

Load NIF

Loading a rust NIF is no different from ordinary NIF. The actual loading is through callingRustler.load_nif(<LIBRARY_NAME>)Completed, usually used in elixir@on_loadHook to achieve

defmodule MyProject.NativeModule do
  @on_load :load_nif

  defp load_nif do
    :ok = Rustler.load_nif("<LIBRARY_NAME>")
  end

  // When loading a NIF module, dummy clauses for all NIF functions are required.
  // NIF dummies usually just error out when called when the NIF is not loaded, as that should
  // never normally happen.
  def my_native_function(_arg1, _arg2), do: exit(:nif_not_loaded)
end

be careful<LIBRARY_NAME>yesCargo.tomlIn the file[lib]Library name in

Dependence on rustler

openRustlerofCargo.tomlFile, we see the following code

[dependencies]
ruster_unsafe = ">=0.4"
libc = ">=0.1"
lazy_static = "0.1.*"

It depends onruster_unsafeTo develop NIF with rust,ruster_unsafeIt is an underlying Erlang NIF language binding, and rustler is just an assistant tool integrated into elixir