Crate erlang_nif_sys [−] [src]
Low level Rust bindings to the Erlang NIF API.
NIF Crate
A NIF module is built by creating a new crate that uses erlang_nif-sys
as a dependency.
(more)
NIF Functions
All NIF functions must have the following signature:
#[macro_use] extern crate erlang_nif_sys; use erlang_nif_sys::*; 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 erlang_nif_sys; use erlang_nif_sys::*; nif_init!("my_nif_module",[ ("my_nif_fun1", 1, my_nif_fun1), ("my_dirty_fun2", 1, my_dirty_fun2, ERL_NIF_DIRTY_JOB_CPU_BOUND) ], {load: my_load} );
Details
The erlang_nif-sys
analog of ERL_NIF_INIT()
is nif_init!
which has the following form:
nif_init!(module_name, [nif_funcs], {options})
module_name
must be a string literal, for example "mynifmodule"
.
nif_funcs
declares all the exported NIF functions for this module. Each entry is declared as
(name, arity, function, flags)
name
is a string literal indicating the name of the function as seen from Erlang code.
arity
is an integer indicating how many parameter this function takes as seen from Erlang code.
function
is the Rust implentation of the NIF and must be of the form
Fn(env: *mut ErlNifEnv, argc: c_int, args: *const ERL_NIF_TERM) -> ERL_NIF_TERM
. This is usually a plain
Rust function, but closures are permitted.
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.
The options
are the NIF module intialization functions load
, reload
,
upgrade
, and unload
.
Each is optional and is specified in struct-init style if present. If no options are needed,
the curly braces may be elided. Stub implementation of all these functions looks something like:
#[macro_use] extern crate erlang_nif_sys; use erlang_nif_sys::*; nif_init!("mymod", [], {load: load, reload: reload, upgrade: upgrade, unload: unload}); fn load(env: *mut ErlNifEnv, priv_data: *mut *mut c_void, load_info: ERL_NIF_TERM)-> c_int { 0 } fn reload(env: *mut ErlNifEnv, priv_data: *mut *mut c_void, load_info: ERL_NIF_TERM) -> c_int { 0 } 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 } fn unload(env: *mut ErlNifEnv, priv_data: *mut c_void) {}
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 erlang_nif_sys; use erlang_nif_sys::*; use std::mem; fn native_add(env: *mut ErlNifEnv, argc: c_int, args: *const ERL_NIF_TERM) -> ERL_NIF_TERM { unsafe { let mut a: c_int = mem::uninitialized(); let mut b: c_int = mem::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) } } }
Reexports
pub use erlang_nif_sys_api::*; |
Modules
erlang_nif_sys_api |
Macros
enif_fprintf |
See enif_fprintf in the Erlang docs. |
enif_make_list |
See enif_make_list in the Erlang docs. |
enif_make_tuple |
See enif_make_tuple in the Erlang docs. |
enif_snprintf |
See enif_snprintf in the Erlang docs. |
nif |
Create ErlNifFunc structure. Use inside |
nif_init |
Implement exported module init function needed by the Erlang runtime. |
platform_nif_init |
Platform specific NIF module initialization. |
slice_args |
Wrapper to deliver NIF args as Rust slice. |