Skip to content

Instantly share code, notes, and snippets.

@LeebDeveloper
Created June 30, 2014 15:25
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save LeebDeveloper/38c9a2b7cf169333f9c8 to your computer and use it in GitHub Desktop.
Save LeebDeveloper/38c9a2b7cf169333f9c8 to your computer and use it in GitHub Desktop.
Erlang NIF in pure Rust
-module(niftest).
-export([add/2]).
-on_load(init/0).
init() ->
ok = erlang:load_nif("./nif", 0).
add(_, _) ->
exit(nif_library_not_loaded).
#![crate_id="rusthello#0.0"]
#![crate_type="dylib"]
extern crate libc;
use libc::{c_char,c_void};
use std::c_vec::CVec;
//use std::c_str::{CString};
type ErlNifTerm = u32;
type ErlNifEnv = *const libc::c_void;
#[nolink]
extern {
fn enif_get_int(env: *const ErlNifEnv, term: ErlNifTerm, ip: *mut i32) -> i32;
fn enif_make_int(env: *const ErlNifEnv, i: i32) -> ErlNifTerm;
}
extern fn add_nif(env: *const ErlNifEnv, argc: i32, argv: *mut ErlNifTerm) -> ErlNifTerm {
unsafe {
let mut a:i32 = 0;
let mut b:i32 = 0;
let t = CVec::new(argv, argc as uint);
let arguments = t.as_slice();
enif_get_int(env, arguments[0], &mut a);
enif_get_int(env, arguments[1], &mut b);
enif_make_int(env, a + b)
}
}
#[packed]
pub struct ErlNifFunc {
name : *const libc::c_char,
arity : u32,
fptr : extern fn(env: *const ErlNifEnv, argc: i32, argv: *mut ErlNifTerm) -> ErlNifTerm
}
#[packed]
pub struct ErlNifEntry {
major : i32,
minor : i32,
name : *const libc::c_char,
num_of_funcs : i32,
funcs : *const ErlNifFunc,
load : Option<extern "C" fn(env: *const ErlNifEnv, priv_data: *const libc::c_void, load_info: ErlNifTerm) -> i32>,
reload : Option<extern "C" fn(env: *const ErlNifEnv, priv_data: *const libc::c_void, load_info: ErlNifTerm) -> i32>,
upgrade : Option<extern "C" fn(env: *const ErlNifEnv, priv_data: *const libc::c_void, old_priv_data: *const libc::c_void, load_info: ErlNifTerm) -> i32>,
unload : Option<extern "C" fn(env: *const ErlNifEnv, priv_data: *const libc::c_void)>,
vm_variant : *const libc::c_char
}
static mut FunTbl : [ErlNifFunc, ..1] =
[ErlNifFunc{
name : 0 as *const libc::c_char,
arity : 2,
fptr : add_nif
}];
static mut NifEntry : ErlNifEntry = ErlNifEntry {
major : 2,
minor : 4,
name : 0 as *const libc::c_char,
num_of_funcs : 1,
funcs : 0 as *const ErlNifFunc,
load : None,
reload : None,
upgrade : None,
unload : None,
vm_variant : 0 as *const libc::c_char
};
#[no_mangle]
pub extern "C" fn nif_init() -> *const ErlNifEntry {
unsafe {
FunTbl[0].name = "add".to_c_str().unwrap();
NifEntry.name = "niftest".to_c_str().unwrap();
NifEntry.funcs = FunTbl.as_ptr();
NifEntry.vm_variant = "beam.vanilla".to_c_str().unwrap();
let p: *const ErlNifEntry = &NifEntry;
p
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment