4个版本 (重大变更)
使用旧的Rust 2015
0.4.0 | 2016年3月20日 |
---|---|
0.3.0 | 2016年1月21日 |
0.2.0 | 2015年8月18日 |
0.1.0 | 2015年4月22日 |
#10 in #nif
被ruster使用
36KB
448 行
Ruster (不安全)
一个用于在Rust中创建Erlang NIF模块的crate。此crate暴露了原始的C NIF API,可以直接使用或作为高层接口crate的基础。支持Unix和Windows。
请参阅crate文档。
感谢Radosław Szymczyszyn在我Rust FFI冒险中给予指导,并提供了原始的自动绑定。
lib.rs
:
对Erlang NIF API的低级Rust绑定。
NIF Crate
一个NIF模块是通过创建一个新的crate来构建的,该crate使用ruster_unsafe
作为依赖项。(更多内容)
NIF函数
所有NIF函数都必须有以下签名
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模块初始化
对于急于求成的人
#[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)
);
详细信息
ruster_unsafe
中的ERL_NIF_INIT()
的对应物是nif_init!
,其形式如下
nif_init!(module_name,load,reload,upgrade,unload,niffunc0,niffunc1, ...)
module_name
必须是一个空终止的字节序列,例如 b"mynifmodule\0"
。
load, reload, upgrade, 和 unload 是可选的函数。请参阅Erlang文档中的load、reload、upgrade 和 unload。Rust中的存根实现是
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!
在 nif_init!
内声明NIF函数
nif!(nif_name,arity,nif_func,flags)
nif_name
必须是一个空终止的字节序列,例如 b"my_nif_fun1\0"
。 arity
是函数接受的参数数量。 nif_func
是NIF的Rust实现。 flags
是可选的,允许您指定此NIF是否要在脏调度器上运行。请参阅Erlang文档中的脏NIFs。
调用NIF API
与任何Rust FFI调用一样,NIF API调用必须被包裹在unsafe
块中。以下是一个调用NIF API的示例以及处理args
参数的方法。
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)
}
}
}
示例
完整示例请参见(ruster_demo)
注意和限制
- 已在Linux上测试,但任何Unix系统都应适用。
- 计划支持Windows,但目前尚未实现。
- NIF线程API尚未实现,因为Rust提供了自己优秀的、可移植的线程API。但如果需要,可以实现。
- Varargs NIF函数尚未实现。
- ruster_unsafe基于Radosław Szymczyszyn的工作(https://github.com/lavrin/erlang-rust-nif)
依赖项
~43KB