diff options
Diffstat (limited to 'system/doc/tutorial/nif.xmlsrc')
-rw-r--r-- | system/doc/tutorial/nif.xmlsrc | 127 |
1 files changed, 70 insertions, 57 deletions
diff --git a/system/doc/tutorial/nif.xmlsrc b/system/doc/tutorial/nif.xmlsrc index 8ddad60f74..c79370e8c8 100644 --- a/system/doc/tutorial/nif.xmlsrc +++ b/system/doc/tutorial/nif.xmlsrc @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2000</year><year>2013</year> + <year>2000</year><year>2015</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -28,92 +28,105 @@ <rev></rev> <file>nif.xml</file> </header> - <p>This is an example of how to solve the <seealso marker="example">example problem</seealso> - by using NIFs. NIFs were introduced in R13B03 as an experimental - feature. It is a simpler and more efficient way of calling C-code - than using port drivers. NIFs are most suitable for synchronous functions like - <c>foo</c> and <c>bar</c> in the example, that does some - relatively short calculations without side effects and return the result.</p> - <section> - <title>NIFs</title> - <p>A NIF (Native Implemented Function) is a function that is - implemented in C instead of Erlang. NIFs appear as any other functions to - the callers. They belong to a module and are called like any other Erlang - functions. The NIFs of a module are compiled and linked into a dynamic - loadable shared library (SO in Unix, DLL in Windows). The NIF library must - be loaded in runtime by the Erlang code of the module.</p> - <p>Since a NIF library is dynamically linked into the emulator - process, this is the fastest way of calling C-code from Erlang (alongside - port drivers). Calling NIFs requires no context switches. But it is also - the least safe, because a crash in a NIF will bring the emulator down - too.</p> - </section> + <p>This section outlines an example of how to solve the example + problem in <seealso marker="example">Problem Example</seealso> + by using Native Implemented Functions (NIFs).</p> + <p>NIFs were introduced in Erlang/OTP R13B03 as an experimental + feature. It is a simpler and more efficient way of calling C-code + than using port drivers. NIFs are most suitable for synchronous + functions, such as <c>foo</c> and <c>bar</c> in the example, that + do some relatively short calculations without side effects and + return the result.</p> + <p>A NIF is a function that is implemented in C instead of Erlang. + NIFs appear as any other functions to the callers. They belong to + a module and are called like any other Erlang functions. The NIFs + of a module are compiled and linked into a dynamic loadable, + shared library (SO in UNIX, DLL in Windows). The NIF library must + be loaded in runtime by the Erlang code of the module.</p> + <p>As a NIF library is dynamically linked into the emulator process, + this is the fastest way of calling C-code from Erlang (alongside + port drivers). Calling NIFs requires no context switches. But it + is also the least safe, because a crash in a NIF brings the + emulator down too.</p> <section> <title>Erlang Program</title> - <p>Even if all functions of a module will be NIFs, you still need an Erlang - module for two reasons. First, the NIF library must be explicitly loaded - by Erlang code in the same module. Second, all NIFs of a module must have - an Erlang implementation as well. Normally these are minimal stub - implementations that throw an exception. But it can also be used as - fallback implementations for functions that do not have native - implemenations on some architectures.</p> - <p>NIF libraries are loaded by calling <c>erlang:load_nif/2</c>, with the - name of the shared library as argument. The second argument can be any - term that will be passed on to the library and used for - initialization.</p> + <p>Even if all functions of a module are NIFs, an Erlang + module is still needed for two reasons:</p> + <list type="bulleted"> + <item>The NIF library must be explicitly loaded by + Erlang code in the same module.</item> + <item>All NIFs of a module must have an Erlang implementation + as well.</item> + </list> + <p>Normally these are minimal stub implementations that throw an + exception. But they can also be used as fallback implementations + for functions that do not have native implemenations on some + architectures.</p> + <p>NIF libraries are loaded by calling <c>erlang:load_nif/2</c>, + with the name of the shared library as argument. The second + argument can be any term that will be passed on to the library + and used for initialization:</p> <codeinclude file="complex6.erl" tag="" type="none"></codeinclude> - <p>We use the directive <c>on_load</c> to get function <c>init</c> to be - automatically called when the module is loaded. If <c>init</c> - returns anything other than <c>ok</c>, such when the loading of - the NIF library fails in this example, the module will be - unloaded and calls to functions within it will fail.</p> - <p>Loading the NIF library will override the stub implementations + <p>Here, the directive <c>on_load</c> is used to get function + <c>init</c> to be automatically called when the module is + loaded. If <c>init</c> returns anything other than <c>ok</c>, + such when the loading of the NIF library fails in this example, + the module is unloaded and calls to functions within it, + fail.</p> + <p>Loading the NIF library overrides the stub implementations and cause calls to <c>foo</c> and <c>bar</c> to be dispatched to the NIF implementations instead.</p> </section> <section> - <title>NIF library code</title> + <title>NIF Library Code</title> <p>The NIFs of the module are compiled and linked into a shared library. Each NIF is implemented as a normal C function. The macro <c>ERL_NIF_INIT</c> together with an array of structures defines the names, - arity and function pointers of all the NIFs in the module. The header - file <c>erl_nif.h</c> must be included. Since the library is a shared - module, not a program, no main function should be present.</p> + arity, and function pointers of all the NIFs in the module. The header + file <c>erl_nif.h</c> must be included. As the library is a shared + module, not a program, no main function is to be present.</p> <p>The function arguments passed to a NIF appears in an array <c>argv</c>, - with <c>argc</c> as the length of the array and thus the arity of the + with <c>argc</c> as the length of the array, and thus the arity of the function. The Nth argument of the function can be accessed as <c>argv[N-1]</c>. NIFs also take an environment argument that serves as an opaque handle that is needed to be passed on to most API functions. The environment contains information about - the calling Erlang process.</p> + the calling Erlang process:</p> <codeinclude file="complex6_nif.c" tag="" type="none"></codeinclude> - <p>The first argument to <c>ERL_NIF_INIT</c> must be the name of the + <p>Here,<c>ERL_NIF_INIT</c> has the following arguments:</p> + <list type="bulleted"> + <item><p>The first argument must be the name of the Erlang module as a C-identifier. It will be stringified by the - macro. The second argument is the array of <c>ErlNifFunc</c> - structures containing name, arity and function pointer of - each NIF. The other arguments are pointers to callback functions - that can be used to initialize the library. We do not use them - in this simple example so we set them all to <c>NULL</c>.</p> + macro.</p> + </item> + <item>The second argument is the array of <c>ErlNifFunc</c> + structures containing name, arity, and function pointer of + each NIF.</item> + <item>The remaining arguments are pointers to callback functions + that can be used to initialize the library. They are not used + in this simple example, hence they are all set to <c>NULL</c>.</item> + </list> <p>Function arguments and return values are represented as values - of type <c>ERL_NIF_TERM</c>. We use functions like <c>enif_get_int</c> - and <c>enif_make_int</c> to convert between Erlang term and C-type. - If the function argument <c>argv[0]</c> is not an integer then - <c>enif_get_int</c> will return false, in which case we return + of type <c>ERL_NIF_TERM</c>. Here, functions like <c>enif_get_int</c> + and <c>enif_make_int</c> are used to convert between Erlang term + and C-type. + If the function argument <c>argv[0]</c> is not an integer, + <c>enif_get_int</c> returns false, in which case it returns by throwing a <c>badarg</c>-exception with <c>enif_make_badarg</c>.</p> </section> <section> <title>Running the Example</title> - <p>1. Compile the C code.</p> + <p><em>Step 1.</em> Compile the C code:</p> <pre> unix> <input>gcc -o complex6_nif.so -fpic -shared complex.c complex6_nif.c</input> windows> <input>cl -LD -MD -Fe complex6_nif.dll complex.c complex6_nif.c</input></pre> - <p>2. Start Erlang and compile the Erlang code.</p> + <p><em>Step 2:</em> Start Erlang and compile the Erlang code:</p> <pre> > <input>erl</input> Erlang R13B04 (erts-5.7.5) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false] @@ -121,7 +134,7 @@ Erlang R13B04 (erts-5.7.5) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-p Eshell V5.7.5 (abort with ^G) 1> <input>c(complex6).</input> {ok,complex6}</pre> - <p>3. Run the example.</p> + <p><em>Step 3:</em> Run the example:</p> <pre> 3> <input>complex6:foo(3).</input> 4 |