1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/*!
Low level Rust bindings to the [Erlang NIF API](http://www.erlang.org/doc/man/erl_nif.html).
# 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:
```
use rustler_sys::*;
# fn main(){} //0
fn my_nif(env: *mut ErlNifEnv,
argc: c_int,
args: *const ERL_NIF_TERM) -> ERL_NIF_TERM {
// ...
# unsafe{enif_make_badarg(env)}
}
```
# NIF Module Initialization
## For the Impatient
```
use rustler_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}
);
# fn main(){} //1
# fn my_load(env: *mut ErlNifEnv, priv_data: *mut *mut c_void, load_info: ERL_NIF_TERM)-> c_int { 0 }
# fn my_nif_fun1(_: *mut ErlNifEnv,_: c_int,args: *const ERL_NIF_TERM) -> ERL_NIF_TERM {unsafe{*args}}
# fn my_dirty_fun2(_: *mut ErlNifEnv,_: c_int,args: *const ERL_NIF_TERM) -> ERL_NIF_TERM {unsafe{*args}}
```
## Details
The `erlang_nif-sys` analog of [`ERL_NIF_INIT()`](http://www.erlang.org/doc/man/erl_nif_init.html) 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 implementation 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](http://www.erlang.org/doc/man/erl_nif.html#dirty_nifs)
in the Erlang docs.
The `options` are the NIF module initialization functions [`load`](http://www.erlang.org/doc/man/erl_nif.html#load), [`reload`](http://www.erlang.org/doc/man/erl_nif.html#reload),
[`upgrade`](http://www.erlang.org/doc/man/erl_nif.html#upgrade), and [`unload`](http://www.erlang.org/doc/man/erl_nif.html#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:
```
use rustler_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) {}
# fn main(){} //2
```
# 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.
```
use rustler_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)
}
}
}
# fn main(){} //3
```
*/
// Don't throw warnings on NIF naming conventions
#![allow(non_camel_case_types)]
#[macro_use]
mod initmacro;
pub mod rustler_sys_api;
pub use crate::rustler_sys_api::*;