Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 150

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../otp_doc.css" type="text/css">
<title>Erlang -- NIFs</title>
</head>
<body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container">
<script id="js" type="text/javascript" language="JavaScript" src="../js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript">
            <!--
              function getWinHeight() {
                var myHeight = 0;
                if( typeof( window.innerHeight ) == 'number' ) {
                  //Non-IE
                  myHeight = window.innerHeight;
                } else if( document.documentElement && ( document.documentElement.clientWidth ||
                                                         document.documentElement.clientHeight ) ) {
                  //IE 6+ in 'standards compliant mode'
                  myHeight = document.documentElement.clientHeight;
                } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
                  //IE 4 compatible
                  myHeight = document.body.clientHeight;
                }
                return myHeight;
              }

              function setscrollpos() {
                var objf=document.getElementById('loadscrollpos');
                 document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2;
              }

              function addEvent(obj, evType, fn){
                if (obj.addEventListener){
                obj.addEventListener(evType, fn, true);
                return true;
              } else if (obj.attachEvent){
                var r = obj.attachEvent("on"+evType, fn);
                return r;
              } else {
                return false;
              }
             }

             addEvent(window, 'load', setscrollpos);

             //--></script><div id="leftnav"><div class="innertube">
<img alt="Erlang logo" src="../erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="../pdf/otp-system-documentation-5.9.3.1.pdf">PDF</a><br><a href="../index.html">Top</a></small><p><strong>Interoperability Tutorial</strong><br><strong>User's Guide</strong><br><small>Version 5.9.3.1</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p>
<ul class="flipMenu" imagepath="../js/flipmenu">
<li id="no" title="Introduction" expanded="false">Introduction<ul>
<li><a href="introduction.html">
              Top of chapter
            </a></li>
<li title="Purpose"><a href="introduction.html#id60800">Purpose</a></li>
<li title="Prerequisites"><a href="introduction.html#id60757">Prerequisites</a></li>
</ul>
</li>
<li id="no" title="Overview" expanded="false">Overview<ul>
<li><a href="overview.html">
              Top of chapter
            </a></li>
<li title="Built-In Mechanisms"><a href="overview.html#id62194">Built-In Mechanisms</a></li>
<li title="C and Java Libraries"><a href="overview.html#id60915">C and Java Libraries</a></li>
<li title="Standard Protocols"><a href="overview.html#id62774">Standard Protocols</a></li>
<li title="IC"><a href="overview.html#id61047">IC</a></li>
<li title="Old Applications"><a href="overview.html#id62555">Old Applications</a></li>
</ul>
</li>
<li id="no" title="Problem Example" expanded="false">Problem Example<ul>
<li><a href="example.html">
              Top of chapter
            </a></li>
<li title="Description"><a href="example.html#id63860">Description</a></li>
</ul>
</li>
<li id="no" title="Ports" expanded="false">Ports<ul>
<li><a href="c_port.html">
              Top of chapter
            </a></li>
<li title="Erlang Program"><a href="c_port.html#id58262">Erlang Program</a></li>
<li title="C Program"><a href="c_port.html#id62416">C Program</a></li>
<li title="Running the Example"><a href="c_port.html#id63496">Running the Example</a></li>
</ul>
</li>
<li id="no" title="Erl_Interface" expanded="false">Erl_Interface<ul>
<li><a href="erl_interface.html">
              Top of chapter
            </a></li>
<li title="Erlang Program"><a href="erl_interface.html#id63174">Erlang Program</a></li>
<li title="C Program"><a href="erl_interface.html#id63282">C Program</a></li>
<li title="Running the Example"><a href="erl_interface.html#id61784">Running the Example</a></li>
</ul>
</li>
<li id="no" title="Port drivers" expanded="false">Port drivers<ul>
<li><a href="c_portdriver.html">
              Top of chapter
            </a></li>
<li title="Port Drivers"><a href="c_portdriver.html#id61981">Port Drivers</a></li>
<li title="Erlang Program"><a href="c_portdriver.html#id62001">Erlang Program</a></li>
<li title="C Driver"><a href="c_portdriver.html#id62119">C Driver</a></li>
<li title="Running the Example"><a href="c_portdriver.html#id63970">Running the Example</a></li>
</ul>
</li>
<li id="no" title="C Nodes" expanded="false">C Nodes<ul>
<li><a href="cnode.html">
              Top of chapter
            </a></li>
<li title="Erlang Program"><a href="cnode.html#id64088">Erlang Program</a></li>
<li title="C Program"><a href="cnode.html#id64168">C Program</a></li>
<li title="Running the Example"><a href="cnode.html#id64499">Running the Example</a></li>
</ul>
</li>
<li id="loadscrollpos" title="NIFs" expanded="true">NIFs<ul>
<li><a href="nif.html">
              Top of chapter
            </a></li>
<li title="NIFs"><a href="nif.html#id64799">NIFs</a></li>
<li title="Erlang Program"><a href="nif.html#id64820">Erlang Program</a></li>
<li title="NIF library code"><a href="nif.html#id64884">NIF library code</a></li>
<li title="Running the Example"><a href="nif.html#id64985">Running the Example</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<h1>8 NIFs</h1>
  
  <p>This is an example of how to solve the <span class="bold_code"><a href="example.html">example problem</a></span>
     by using NIFs. NIFs where 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
     <span class="code">foo</span> and <span class="code">bar</span> in the example, that does some
     relatively short calculations without side effects and return the result.</p>
  <h3><a name="id64799">8.1 
        NIFs</a></h3>
    
    <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>
  

  <h3><a name="id64820">8.2 
        Erlang Program</a></h3>
    
    <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 <span class="code">erlang:load_nif/2</span>, 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>

<div class="example"><pre>

-module(complex6).
-export([foo/1, bar/1]).
-on_load(init/0).

init() -&gt;
    ok = erlang:load_nif("./complex6_nif", 0).

foo(_X) -&gt;
    exit(nif_library_not_loaded).
bar(_Y) -&gt;
    exit(nif_library_not_loaded).
</pre></div>
    <p>We use the directive <span class="code">on_load</span> to get function <span class="code">init</span> to be
      automatically called when the module is loaded. If <span class="code">init</span>
      returns anything other than <span class="code">ok</span>, 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
      and cause calls to <span class="code">foo</span> and <span class="code">bar</span> to be dispatched to
      the NIF implementations instead.</p>
  
  <h3><a name="id64884">8.3 
        NIF library code</a></h3>
    
    <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
      <span class="code">ERL_NIF_INIT</span> together with an array of structures defines the names,
      arity and function pointers of all the NIFs in the module. The header
      file <span class="code">erl_nif.h</span> must be included. Since the library is a shared
      module, not a program, no main function should be present.</p>
    <p>The function arguments passed to a NIF appears in an array <span class="code">argv</span>,
      with <span class="code">argc</span> as the length of the array and thus the arity of the
      function. The Nth argument of the function can be accessed as
      <span class="code">argv[N-1]</span>. NIFs also takes 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>

<div class="example"><pre>

#include "erl_nif.h"

extern int foo(int x);
extern int bar(int y);

static ERL_NIF_TERM foo_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    int x, ret;
    if (!enif_get_int(env, argv[0], &amp;x)) {
	return enif_make_badarg(env);
    }
    ret = foo(x);
    return enif_make_int(env, ret);
}

static ERL_NIF_TERM bar_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    int y, ret;
    if (!enif_get_int(env, argv[0], &amp;y)) {
	return enif_make_badarg(env);
    }
    ret = bar(y);
    return enif_make_int(env, ret);
}

static ErlNifFunc nif_funcs[] = {
    {"foo", 1, foo_nif},
    {"bar", 1, bar_nif}
};

ERL_NIF_INIT(complex6, nif_funcs, NULL, NULL, NULL, NULL)

</pre></div>
    <p>The first argument to <span class="code">ERL_NIF_INIT</span> 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 <span class="code">ErlNifFunc</span>
      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
      is this simple example so we set them all to <span class="code">NULL</span>.</p>
    <p>Function arguments and return values are represented as values
      of type <span class="code">ERL_NIF_TERM</span>. We use functions like <span class="code">enif_get_int</span> 
      and <span class="code">enif_make_int</span> to convert between Erlang term and C-type. 
      If the function argument <span class="code">argv[0]</span> is not an integer then
      <span class="code">enif_get_int</span> will return false, in which case we return
      by throwing a <span class="code">badarg</span>-exception with <span class="code">enif_make_badarg</span>.</p>
  

  <h3><a name="id64985">8.4 
        Running the Example</a></h3>
    
    <p>1. Compile the C code.</p>
    <div class="example"><pre>
unix&gt; <span class="bold_code">gcc -o complex6_nif.so -fpic -shared complex.c complex6_nif.c</span>
windows&gt; <span class="bold_code">cl -LD -MD -Fe complex6_nif.dll complex.c complex6_nif.c</span></pre></div>
    <p>2. Start Erlang and compile the Erlang code.</p>
    <div class="example"><pre>
&gt; <span class="bold_code">erl</span>
Erlang R13B04 (erts-5.7.5) [64-bit] [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]

Eshell V5.7.5  (abort with ^G)
1&gt; <span class="bold_code">c(complex6).</span>
{ok,complex6}</pre></div>
    <p>3. Run the example.</p>
<div class="example"><pre>
3&gt; <span class="bold_code">complex6:foo(3).</span>
4
4&gt; <span class="bold_code">complex6:bar(5).</span>
10
5&gt; <span class="bold_code">complex6:foo("not an integer").</span>
** exception error: bad argument
     in function  complex6:foo/1
        called as comlpex6:foo("not an integer")
</pre></div>

</div>
<div class="footer">
<hr>
<p>Copyright © 2000-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>