erl_nif 擴展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) [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很簡單,而且高效。
發佈了66 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章