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') 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