4 releases (breaking)
Uses old Rust 2015
0.4.0 | Mar 20, 2016 |
---|---|
0.3.0 | Jan 21, 2016 |
0.2.0 | Aug 18, 2015 |
0.1.0 | Apr 22, 2015 |
#10 in #nif
Used in ruster
36KB
448 lines
Ruster (unsafe)
A crate for creating Erlang NIF modules in Rust. This crate exposes the raw C NIF API which can be used directly or as a foundation for higher layer interface crates. Supported under Unix and Windows.
See the crate documention.
See ruster_unsafe_demo.
Thanks go to Radosław Szymczyszyn for bootstrapping me on this Rust FFI adventure and providing the original automatic bindings.
lib.rs
:
Low level Rust bindings to the Erlang NIF API.
NIF Crate
A NIF module is built by creating a new crate that uses ruster_unsafe
as a dependency.
(more)
NIF Functions
All NIF functions must have the following signature:
extern crate ruster_unsafe;
use ruster_unsafe::*;
extern "C" fn my_nif(env: *mut ErlNifEnv,
argc: c_int,
args: *const ERL_NIF_TERM) -> ERL_NIF_TERM {
// ...
}
NIF Module Initialization
For the Impatient
#[macro_use]
extern crate ruster_unsafe;
use ruster_unsafe::*;
nif_init!(b"my_nif_module\0", Some(load), None, None, None,
nif!(b"my_nif_fun1\0", 1, my_nif_fun1),
nif!(b"my_dirty_fun2\0", 1, my_dirty_fun2, ERL_NIF_DIRTY_JOB_CPU_BOUND)
);
Details
The ruster_unsafe
analog of ERL_NIF_INIT()
is nif_init!
which has the following form:
nif_init!(module_name, load, reload, upgrade, unload, niffunc0, niffunc1, ...)
module_name
must be a null-terminated byte array, for example b"mynifmodule\0"
.
load, reload, upgrade, and unload are optional functions. See load, reload, upgrade, and unload in the Erlang docs. Stub implementations in Rust are:
extern "C" fn load(env: *mut ErlNifEnv,
priv_data: *mut *mut c_void,
load_info: ERL_NIF_TERM)-> c_int { 0 }
extern "C" fn reload(env: *mut ErlNifEnv,
priv_data: *mut *mut c_void,
load_info: ERL_NIF_TERM) -> c_int { 0 }
extern "C" fn upgrade(env: *mut ErlNifEnv,
priv_data: *mut *mut c_void,
old_priv_data: *mut *mut c_void,
load_info: ERL_NIF_TERM) -> c_int { 0 }
extern "C" fn unload(env: *mut ErlNifEnv,
priv_data: *mut c_void) {}
nif!
declares NIF functions inside nif_init!
:
nif!(nif_name, arity, nif_func, flags)
nif_name
must be a null-terminated byte array, for example b"my_nif_fun1\0"
.
arity
is the number of parameters accepted by the function. nif_func
is the Rust implementation of the NIF. flags
is optional
and allows you to specify if this NIF is to run on a dirty scheduler. See dirty NIFs
in the Erlang docs.
Invoking NIF API
As with any Rust FFI call, NIF API calls must be wrapped in unsafe
blocks.
Below is an example of invoking NIF APIs along with an approach for dealing with
the the args
parameter.
extern crate ruster_unsafe;
use ruster_unsafe::*;
use std::mem::uninitialized;
extern "C" fn native_add(env: *mut ErlNifEnv,
argc: c_int,
args: *const ERL_NIF_TERM) -> ERL_NIF_TERM {
unsafe {
let mut a:c_int = uninitialized();
let mut b:c_int = uninitialized();
if argc == 2 &&
0 != enif_get_int(env, *args, &mut a) &&
0 != enif_get_int(env, *args.offset(1), &mut b) {
enif_make_int(env, a+b)
}
else {
enif_make_badarg(env)
}
}
}
Examples
For a complete example see (ruster_demo)
Notes and Limitations
- Tested on Linux, but any unix should be fine.
- Windows support is planned but not currently implemented.
- The NIF threading API is not implemented since Rust provides its own excellent, portable threading API. But this could be implemented if there is a need.
- Varargs NIF functions are not implemented.
- ruster_unsafe is based on work by Radosław Szymczyszyn (https://github.com/lavrin/erlang-rust-nif)
Dependencies
~43KB