#nif #erlang #ffi

ruster_unsafe

使用C NIF API在Rust中创建Erlang NIF模块

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使用

MIT/Apache

36KB
448

Ruster (不安全)

一个用于在Rust中创建Erlang NIF模块的crate。此crate暴露了原始的C NIF API,可以直接使用或作为高层接口crate的基础。支持Unix和Windows。

请参阅crate文档

请参阅ruster_unsafe_demo

感谢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文档中的loadreloadupgradeunload。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