Home > Erlang探索 > erl_nif Erlang的ffi 扩展erlang的另外一种方法

erl_nif Erlang的ffi 扩展erlang的另外一种方法

November 26th, 2009 Leave a comment Go to comments

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: erl_nif Erlang的ffi 扩展erlang的另外一种方法

我们知道扩展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)  [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]</code>

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)  [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]</code>

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

综述: nbif很简单,而且高效。

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Erlang探索 Tags:
  1. crackcell
    November 26th, 2009 at 14:03 | #1

    不知道老大对port、driver和nif的适用场景怎么看?
    现在看来,nif至少方便很多,但不知道效率上和其它2者相比如何。

    [Reply]

  2. November 26th, 2009 at 14:13 | #2

    nif适合简单的模块调用。
    driver和port适合于 有双向通信的那种,也就是说扩展会主动给erl推数据的那种。
    driver内嵌效率更高,但是也更危险。

    我们一般的应用都是简单的从erl->扩展 所以nif基本够用了。

    [Reply]

  3. litaocheng
    November 26th, 2009 at 14:54 | #3

    nif的确是最简单,最直接的方法啊。
    以后就用它了

    [Reply]

  4. hitty
    November 26th, 2009 at 18:10 | #4

    我们刚用上port做产品,看来又要转nif了….

    [Reply]

  5. hitty
    November 26th, 2009 at 18:11 | #5

    最好做个性能对比

    [Reply]

  6. November 26th, 2009 at 18:29 | #6

    性能差太多了 nif除去参数转化外 基本上就是c函数调用 , port和driver的开销相对太大了。 所以这个nif才这么被期待,我都念叨1年了才出来。。。

    [Reply]

  7. hitty
    November 30th, 2009 at 14:45 | #7

    目前看来仅仅是erlang的扩展,不知是否可以此为基础实现与其它语言之间的接口,如python中调用erlang

    [Reply]

  8. November 30th, 2009 at 15:04 | #8

    不靠谱呀 扩展是扩展 嵌入是嵌入呀

    [Reply]

  9. sgqt
    July 5th, 2010 at 11:37 | #9

    貌似你的代码在14上面会报错.
    修改后就好了:
    /* niftest.c */
    #include “erl_nif.h”
    static ERL_NIF_TERM hello(ErlNifEnv* env,int argc, const ERL_NIF_TERM argv[])
    {
    return enif_make_string(env, “hello!”,ERL_NIF_LATIN1);
    }
    static ErlNifFunc nif_funcs[] =
    {
    {“hello”, 0, hello}
    };
    ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)

    [Reply]

    Yu Feng Reply:

    NIF的接口在R14A发布后才差不多固定下来. 之前的版本变化的很厉害,这个example代码是写在NIF第一版实现的基础上的,可能会有不兼容.

    [Reply]

  10. sgqt
    July 5th, 2010 at 14:11 | #10

    @Yu Feng
    了解

    [Reply]

  1. November 28th, 2009 at 15:57 | #1