수색…


정의

공식 문서 : http://erlang.org/doc/tutorial/nif.html

NIF는 Erlang / OTP R13B03에서 실험적으로 소개되었습니다. 목적은 Erlang 코드에서 C 코드를 호출 할 수있게하는 것입니다.

NIF는 Erlang 대신 C로 구현되지만, include가 발생한 모듈에 속하는 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 에 전달되어 전달되는 유형. 이 구조체는 name, arity, 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