aboutsummaryrefslogtreecommitdiffstats
path: root/system/doc/tutorial/nif.xmlsrc
diff options
context:
space:
mode:
Diffstat (limited to 'system/doc/tutorial/nif.xmlsrc')
-rw-r--r--system/doc/tutorial/nif.xmlsrc127
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