论坛首页 综合技术论坛

erl_nif 扩展erlang的另外一种方法

浏览 3438 次
精华帖 (0) :: 良好帖 (17) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-11-26   最后修改:2009-11-27
我们知道扩展erl有2种方法, driver和port. 这2个方法效率都低,因为都要经过 port机制,对于简单的模块,这个开销有时候是不可接受的。这时候nif来救助了。今天发布的R13B03已经支持了,虽然是实验性质的。erl_nif的代表API functions for an Erlang NIF library。 参考文档:
erl_nif.html 和 erlang.html#erlang:load_nif-2 以及 reference_manual/code_loading.html#id2278318

我们来用nif写个最简单的hello, 来展现nif的威力和简单性。
不啰嗦,直接上代码:

root@nd-desktop:~/niftest# cat niftest.c
/* niftest.c */
#include "erl_nif.h"
static ERL_NIF_TERM hello(ErlNifEnv* env)
{
    return enif_make_string(env, "Hello world!");
}
static ErlNifFunc nif_funcs[] =
{
    {"hello", 0, hello}
};
ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)

root@nd-desktop:~/niftest# cat niftest.erl
-module(niftest).
%-on_load(init/0).
-export([init/0, hello/0]).
init() ->
      ok=erlang:load_nif("./niftest", 0), true.
hello() ->
      "NIF library not loaded".

编译:
root@nd-desktop:~/niftest# gcc -fPIC -shared -o niftest.so niftest.c -I   /usr/local/lib/erlang/usr/include  #你的erl_nif.h路径

运行:
root@nd-desktop:~/niftest# erl
Erlang R13B03 (erts-5.7.4) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.4  (abort with ^G)
1> c(niftest).
{ok,niftest}
2> niftest:hello().
"NIF library not loaded"
3> niftest:init().
ok
4> niftest:hello().
"Hello world!"
5>

现在重新修改下 niftest.erl 把on_load的注释去掉
利用模块的自动加载机制来自动初始化。


root@nd-desktop:~/niftest# erl
Erlang R13B03 (erts-5.7.4) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.4  (abort with ^G)
1> c(niftest).
{ok,niftest}
2> niftest:hello().
"Hello world!"
3>

Note: Nbif参与erlang的公平调度, 你调用了nif函数,VM不保证马上调用你的函数实现,而是要到VM认为合适的时候才调用。

综述: nbif很简单,而且高效。
   发表时间:2009-11-26  
好东西啊,太棒了,谢谢老大把不断挖掘出来的东西共享给我们.

有个问题请教一下,用这东西,是不是可以减少通过port的数据被copy来copy去啊?谢谢
0 请登录后投票
   发表时间:2009-11-27  
这个没有任何的数据copy来copy去, 就是简单的调用c函数,有专门的opcode对应的,是极品的快的。。。
0 请登录后投票
   发表时间:2009-11-27  
whrllm 写道
好东西啊,太棒了,谢谢老大把不断挖掘出来的东西共享给我们.

有个问题请教一下,用这东西,是不是可以减少通过port的数据被copy来copy去啊?谢谢


这里提供了一个hack的办法,直接读取erlang内的数据

不过应该不能修改
0 请登录后投票
   发表时间:2009-11-27  
mryufeng 写道
这个没有任何的数据copy来copy去, 就是简单的调用c函数,有专门的opcode对应的,是极品的快的。。。

是说Erlang内的数据和Port/Driver的数据实际上是同一块吗,那在Port/Driver中用C修改后会怎样
0 请登录后投票
   发表时间:2009-11-27  
port/driver修改实现功能没问题,但是有3个巨大的差别:

1. Nif的函数可以把旧的模块的函数覆盖掉。比如说 旧的M:F有问题, 我可以写个NIF把这个有问题的函数代替掉。而port不能。

2. Nif函数可以直接调用, Port系列的都要通过port_XXXX接口来完成。。

3. Nif调用路径短,效率高。
0 请登录后投票
   发表时间:2009-11-27  
Nbif参与erlang的公平调度, 你调用了nif函数,VM不保证马上调用你的函数实现,而是要到VM认为合适的时候才调用。
0 请登录后投票
   发表时间:2010-01-31  
新问题:如何才能让.so库的内容循环传递到erlang呢? 比如说我有一个100W行的文件,每次在库中读一行就返回给erlang。这个怎么实现?如果用reload或update方式传递,每一次都需要打开文件,而且总是读取第一行,怎么办。。。
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics