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  | 
