Erlang Language
NIF
サーチ…
定義
公式文書: http : //erlang.org/doc/tutorial/nif.html
実験的な特徴として、Erlang / OTP R13B03にNIFが導入されました。目的はErlangコードの中からCコードを呼び出すことができるようにすることです。
NIFはErlangではなくC言語で実装されていますが、Erlangコードのスコープ内には、インクルードが発生したモジュールに属する他の関数として表示されます。 NIFライブラリはコンパイル時にリンクされ、実行時にロードされます。
NIFライブラリはエミュレータプロセスに動的にリンクされているため、高速ですが危険です。これは、NIFをクラッシュさせるとエミュレータがダウンするためです。
例:現在のUNIX時刻
ここでは、NIFを書く方法を説明するための非常に簡単な例を示します。
ディレクトリ構造:
nif_test
├── c_src
│ ├── Makefile
│ └── nif_test.c
├── rebar.config
└── src
├── nif_test.app.src
└── nif_test.erl
この構造体は、Rebar3を使用して簡単に初期化できます。
$ rebar3 new lib nif_test && cd nif_test && rebar3 new cmake
nif_test.c
内容:
#include "erl_nif.h"
#include "time.h"
static ERL_NIF_TERM now(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
return enif_make_int(env, time(0));
}
static ErlNifFunc nif_funcs[] = {
{"now", 0, now}
};
ERL_NIF_INIT(nif_test,nif_funcs,NULL,NULL,NULL,NULL);
nif_test.erl
内容:
-module(nif_test).
-on_load(init/0).
-export([now/0]).
-define(APPNAME, nif_test).
-define(LIBNAME, nif_test).
%%====================================================================
%% API functions
%%====================================================================
now() -> nif_not_loaded.
%%====================================================================
%% Internal functions
%%====================================================================
init() ->
SoName = case code:priv_dir(?APPNAME) of
{error, bad_name} ->
case filelib:is_dir(filename:join(["..", priv])) of
true -> filename:join(["..", priv, ?LIBNAME]);
_ -> filename:join([priv, ?LIBNAME])
end;
Dir -> filename:join(Dir, ?LIBNAME)
end,
erlang:load_nif(SoName, 0).
rebar.config
内容:
{erl_opts, [debug_info]}.
{deps, []}.
{pre_hooks, [
{"(linux|darwin|solaris)", compile, "make -C c_src"},
{"(freebsd)", compile, "gmake -C c_src"}
]}.
{post_hooks, [
{"(linux|darwin|solaris)", clean, "make -C c_src clean"},
{"(freebsd)", clean, "gmake -C c_src clean"}
]}.
これで例を実行できます:
$ rebar3 shell
===> Verifying dependencies...
===> Compiling nif_test
make: Entering directory '/home/vschroeder/Projects/nif_test/c_src'
cc -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes -fPIC -I /usr/local/lib/erlang/erts-7.3.1/include/ -I /usr/local/lib/erlang/lib/erl_interface-3.8.2/include -c -o /home/vschroeder/Projects/nif_test/c_src/nif_test.o /home/vschroeder/Projects/nif_test/c_src/nif_test.c
cc /home/vschroeder/Projects/nif_test/c_src/nif_test.o -shared -L /usr/local/lib/erlang/lib/erl_interface-3.8.2/lib -lerl_interface -lei -o /home/vschroeder/Projects/nif_test/c_src/../priv/nif_test.so
make: Leaving directory '/home/vschroeder/Projects/nif_test/c_src'
Erlang/OTP 18 [erts-7.3.1] [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V7.3.1 (abort with ^G)
1> nif_test:now().
1469732239
2> nif_test:now().
1469732264
3>
Erlang C API(CからErlang)
公式文書 : http : //erlang.org/doc/man/erl_nif.html
Erlang C APIの最も重要な構造体、型、およびマクロは次のとおりです。
-
ERL_NIF_TERM
:Erlangの用語の型。これは、NIF関数が従わなければならない戻り値の型です。 -
ERL_NIF_INIT(MODULE, ErlNifFunc funcs[], load, reload, upgrade, unload)
:特定のCファイルで定義されたNIFを実際に作成するマクロです。グローバルスコープで評価する必要があります。通常は、Cファイルの最後の行になります。 -
ErlNifFunc
:各NIFがエクスポートされるERL_NIF_INIT
に渡されるERL_NIF_INIT
。この構造体は、名前、アリティ、C関数のpoiter、フラグで構成されています。すべてのNIF定義を持つこのタイプの配列は、ERL_NIF_INIT
に渡すために作成する必要があります。 -
ErlNifEnv
:NIFが実行されているErlang環境。すべてのNIFの最初の引数として環境を渡すことが必須です。この型は不透明であり、Erlang C APIが提供する関数を使用してのみ操作できます。
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow