From f7c1ea4ff481a8dd7bd8c79ae540342fd8213434 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson
Date: Wed, 9 Dec 2009 11:04:51 +0000
Subject: OTP-8304 Incompatible changes in the experimental NIF feature.
Changed the NIF function prototypes in order to allow more than 3
function arguments. Also an incompatible change in the return value
of erlang:load_nif/2. Added support for references, floats and term
comparison in NIFs. Read more in the documentation of erl_nif and
erlang:load_nif/2.
---
erts/doc/src/erl_nif.xml | 196 ++++++++++++++++++++++++++++++-----------------
erts/doc/src/erlang.xml | 13 ++--
2 files changed, 131 insertions(+), 78 deletions(-)
(limited to 'erts/doc/src')
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index c636d65ef3..2033ba8a66 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -34,12 +34,14 @@
erl_nif
API functions for an Erlang NIF library
- The NIF concept is introduced in R13B03 as an
+ The NIF concept was introduced in R13B03 as an
EXPERIMENTAL feature. The interfaces may be changed in any way
- in coming releases. The API introduced in this release is very
- sparse and contains only the most basic functions to read and
- write Erlang terms.
-
+ in coming releases. The API is still sparse and contains only
+ the most basic functions to read and write Erlang terms.
+
R13B04: The function prototypes of the NIFs
+ have changed to expect argc and argv
+ arguments. The arity of a NIF is by that no longer limited to
+ 3.
A NIF library contains native implementation of some functions
of an erlang module. The native implemented functions (NIFs) are
@@ -56,7 +58,7 @@
/* niftest.c */
#include "erl_nif.h"
-static ERL_NIF_TERM hello(ErlNifEnv* env)
+static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return enif_make_string(env, "Hello world!");
}
@@ -100,8 +102,9 @@ ok
A better solution for a real module is to take advantage of
- the new attribute on_load to automatically load the NIF
- library when the module is loaded.
+ the new directive on_load to automatically
+ load the NIF library when the module is loaded.
A loaded NIF library is tied to the Erlang module code version
that loaded it. If the module is upgraded with a new version, the
new code will have to load its own NIF library (or maybe choose not
@@ -190,7 +193,7 @@ ok
DATA TYPES
- ErlDrvEnv
+ ErlNifEnv
-
ErlNifEnv contains information about the context in
which a NIF call is made. This pointer should not be
@@ -205,31 +208,28 @@ ok
typedef struct {
- const char* name;
- unsigned arity;
- ERL_NIF_TERM (*fptr)(ErlNifEnv* env, ...);
+ const char* name;
+ unsigned arity;
+ ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
} ErlNifFunc;
Describes a NIF by its name, arity and implementation.
fptr is a pointer to the function that implements the
- NIF. The number of arguments must match the arity. A NIF of
- arity 2 will thus look like:
-
-
-ERL_NIF_TERM my_nif(ErlNifEnv* env, ERL_NIF_TERM arg1, ERL_NIF_TERM arg2)
-{
- /* ... */
-}
-
- The maximum allowed arity for a NIF is 3 in current implementation.
+ NIF. The argument argv of a NIF will contain the
+ function arguments passed to the NIF and argc is the
+ length of the array, i.e. the function arity. argv[N-1]
+ will thus denote the Nth argument to the NIF. Note that the
+ argc argument allows for the same C function to
+ implement several Erlang functions with different arity (but
+ same name probably).
ErlNifBinary
-
typedef struct {
- unsigned size;
- unsigned char* data;
+ unsigned size;
+ unsigned char* data;
} ErlNifBinary;
ErlNifBinary contains transient information about an
@@ -249,37 +249,36 @@ typedef struct {
- void*enif_get_data(ErlNifEnv* env)
- Get the private data of a NIF library
- Returns the pointer to the private data that was set by load, reload or upgrade.
-
void*enif_alloc(ErlNifEnv* env, size_t size)
Allocate dynamic memory.
- Allocate memory of size bytes.
-
- voidenif_free(ErlNifEnv* env, void* ptr)
- Free dynamic memory
- Free memory allocated by enif_alloc.
-
- intenif_is_binary(ErlNifEnv* env, ERL_NIF_TERM term)
- Determine if a term is a binary
- Return true if term is a binary
-
- intenif_inspect_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, ErlNifBinary* bin)
- Inspect the content of a binary
- Initialize the structure pointed to by bin with
- transient information about the binary term
- bin_term. Return false if bin_term is not a binary.
+ Allocate memory of size bytes. Return NULL if allocation failed.
intenif_alloc_binary(ErlNifEnv* env, unsigned size, ErlNifBinary* bin)
Create a new binary.
Allocate a new binary of size of size
bytes. Initialize the structure pointed to by bin to
- refer to the allocated binary.
+ refer to the allocated binary. Return false if allocation failed.
- voidenif_release_binary(ErlNifEnv* env, ErlNifBinary* bin)
- Release a binary.
- Release a binary obtained from enif_alloc_binary or enif_inspect_binary.
+ intenif_compare(ErlNifEnv* env, ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)
+ Compare two terms
+ Return an integer less than, equal to, or greater than
+ zero if lhs is found, respectively, to be less than,
+ equal, or greater than rhs. Corresponds to the Erlang
+ operators ==, /=, =<, <,
+ >= and > (but not =:= or =/=).
+
+ voidenif_free(ErlNifEnv* env, void* ptr)
+ Free dynamic memory
+ Free memory allocated by enif_alloc.
+
+ void*enif_get_data(ErlNifEnv* env)
+ Get the private data of a NIF library
+ Return the pointer to the private data that was set by load, reload or upgrade.
+
+ intenif_get_double(ErlNifEnv* env, ERL_NIF_TERM term, double* dp)
+ Read a floating-point number term.
+ Set *dp to the floating point value of
+ term or return false if term is not a float.
intenif_get_int(ErlNifEnv* env, ERL_NIF_TERM term, int* ip)
Read an integer term.
@@ -287,45 +286,80 @@ typedef struct {
term or return false if term is not an integer or is
outside the bounds of type int
- intenif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM term, unsigned long* ip)
- Read an unsigned long integer
- Set *ip to the unsigned long integer value of
- term or return false if term is not an unsigned
- integer or is outside the bounds of type unsigned long
-
intenif_get_list_cell(ErlNifEnv* env, ERL_NIF_TERM list, ERL_NIF_TERM* head, ERL_NIF_TERM* tail)
Get head and tail from a list
Set *head and *tail from
list or return false if list is not a non-empty
list.
- ERL_NIF_TERMenif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)
- Make a binary term.
- Make a binary term from bin. Will also release
- the binary.
+ intenif_get_tuple(ErlNifEnv* env, ERL_NIF_TERM term, int* arity, const ERL_NIF_TERM** array)
+ Inspect the elements of a tuple.
+ If term is a tuple, set *array to point
+ to an array containing the elements of the tuple and set
+ *arity to the number of elements. Note that the array
+ is read-only an (*array)[N-1] will be the Nth element of
+ the tuple. *array is undefined if the arity of the tuple
+ is zero.
Return false if term is not a
+ tuple.
- ERL_NIF_TERMenif_make_badarg(ErlNifEnv* env)
- Make a badarg exception.
- Make a badarg exception to be returned from a NIF.
+ intenif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM term, unsigned long* ip)
+ Read an unsigned integer term.
+ Set *ip to the unsigned long integer value of
+ term or return false if term is not an unsigned integer or is
+ outside the bounds of type unsigned long
- ERL_NIF_TERMenif_make_int(ErlNifEnv* env, int i)
- Create an integer term
- Create an integer term.
+ intenif_inspect_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, ErlNifBinary* bin)
+ Inspect the content of a binary
+ Initialize the structure pointed to by bin with
+ transient information about the binary term
+ bin_term. Return false if bin_term is not a binary.
- ERL_NIF_TERMenif_make_ulong(ErlNifEnv* env, unsigned long i)
- Create an integer term from an unsigned long int
- Create an integer term from an unsigned long int.
+ intenif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term)
+ Determine if a term is an atom
+ Return true if term is an atom.
+
+ intenif_is_binary(ErlNifEnv* env, ERL_NIF_TERM term)
+ Determine if a term is a binary
+ Return true if term is a binary
+
+ intenif_is_identical(ErlNifEnv* env, ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)
+ Erlang operator =:=
+ Return true if and only if the two terms are
+ identical. Corresponds to the Erlang operators =:= and
+ =/=.
+
+ intenif_is_ref(ErlNifEnv* env, ERL_NIF_TERM term)
+ Determine if a term is a reference
+ Return true if term is a reference.
ERL_NIF_TERMenif_make_atom(ErlNifEnv* env, const char* name)
Create an atom term
Create an atom term from the C-string name. Atom
terms may be saved and used between NIF calls.
- ERL_NIF_TERMenif_make_tuple(ErlNifEnv* env, unsigned cnt, ...)
- Create a tuple term.
- Create a tuple term of arity cnt. Expects
- cnt number of arguments (after cnt) of type ERL_NIF_TERM as the
- elements of the tuple.
+ ERL_NIF_TERMenif_make_badarg(ErlNifEnv* env)
+ Make a badarg exception.
+ Make a badarg exception to be returned from a NIF.
+
+ ERL_NIF_TERMenif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)
+ Make a binary term.
+ Make a binary term from bin. Will also release
+ the binary.
+
+ ERL_NIF_TERMenif_make_double(ErlNifEnv* env, double d)
+ Create an floating-point term
+ Create an floating-point term from a double.
+
+ intenif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom)
+ Create an existing atom term
+ Try to create the term of an already existing atom from
+ the C-string name. If the atom already exist store the
+ term in *atom and return true, otherwise return
+ false.
+
+ ERL_NIF_TERMenif_make_int(ErlNifEnv* env, int i)
+ Create an integer term
+ Create an integer term.
ERL_NIF_TERMenif_make_list(ErlNifEnv* env, unsigned cnt, ...)
Create a list term.
@@ -337,11 +371,29 @@ typedef struct {
Create a list cell.
Create a list cell [head | tail].
+ ERL_NIF_TERMenif_make_ref(ErlNifEnv* env)
+ Create a reference.
+ Create a reference like erlang:make_ref/0.
+
ERL_NIF_TERMenif_make_string(ErlNifEnv* env, const char* string)
Create a string.
- Creates a list containing the characters of the
+ Create a list containing the characters of the
C-string string.
+ ERL_NIF_TERMenif_make_tuple(ErlNifEnv* env, unsigned cnt, ...)
+ Create a tuple term.
+ Create a tuple term of arity cnt. Expects
+ cnt number of arguments (after cnt) of type ERL_NIF_TERM as the
+ elements of the tuple.
+
+ ERL_NIF_TERMenif_make_ulong(ErlNifEnv* env, unsigned long i)
+ Create an integer term from an unsigned long int
+ Create an integer term from an unsigned long int.
+
+ voidenif_release_binary(ErlNifEnv* env, ErlNifBinary* bin)
+ Release a binary.
+ Release a binary obtained from enif_alloc_binary or enif_inspect_binary.
+
SEE ALSO
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 3f54d0a6f9..871fc0fd63 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -1929,7 +1929,7 @@ os_prompt%
- erlang:load_nif(Path, LoadInfo) -> ok | {error, Reason, Text}
+ erlang:load_nif(Path, LoadInfo) -> ok | {error, {Reason, Text}}
Load NIF library
Path = string()
@@ -1940,9 +1940,10 @@ os_prompt%
- This BIF is currently introduced as an experimental
- feature. The interface may be changed in any way in future
- releases.
+ This BIF is still an experimental feature. The interface
+ may be changed in any way in future releases.
In
+ R13B03 the return value on failure was
+ {error,Reason,Text}.
Loads and links a dynamic library containing native
implemented functions (NIFs) for a module. Path is a
@@ -1957,10 +1958,10 @@ os_prompt%
The call to load_nif/2 must be made
directly from the Erlang code of the module that the
NIF library belongs to.
- It returns either ok, or {error,Reason,Text}
+
It returns either ok, or {error,{Reason,Text}}
if loading fails. Reason is one of the atoms below,
while Text is a human readable string that may give
- some more information about the failure:
+ some more information about the failure.
load_failed
-
--
cgit v1.2.3