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::*;