From e2ecf7de626ecc2c60f9c8738c20820d21403d77 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 9 Dec 2009 13:54:24 +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/emulator/beam/erl_nif.c | 8 ++------ erts/emulator/test/nif_SUITE.erl | 18 ++++++++++++++++-- erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 17 ++++++++++++++++- 3 files changed, 34 insertions(+), 9 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index b09f92d342..2cb93112ae 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -631,12 +631,8 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) for (i=0; i < entry->num_of_funcs && ret==am_ok; i++) { Uint** code_pp; ErlNifFunc* f = &entry->funcs[i]; - if (f->arity > 3) { - ret = load_nif_error(BIF_P,bad_lib,"Function arity too high for NIF %s/%u", - f->name, f->arity); - } - else if (!erts_atom_get(f->name, sys_strlen(f->name), &f_atom) - || (code_pp = get_func_pp(mod->code, f_atom, f->arity))==NULL) { + if (!erts_atom_get(f->name, sys_strlen(f->name), &f_atom) + || (code_pp = get_func_pp(mod->code, f_atom, f->arity))==NULL) { ret = load_nif_error(BIF_P,bad_lib,"Function not found %T:%s/%u", mod_atom, f->name, f->arity); } diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 3d1607475e..e47161fcbc 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -24,12 +24,13 @@ -include("test_server.hrl"). -export([all/1, fin_per_testcase/2, basic/1, reload/1, upgrade/1, heap_frag/1, - types/1, neg/1]). + types/1, many_args/1, neg/1]). +-export([many_args_100/100]). -define(nif_stub,nif_stub_error(?LINE)). all(suite) -> - [basic, reload, upgrade, heap_frag, types, neg]. + [basic, reload, upgrade, heap_frag, types, many_args, neg]. fin_per_testcase(_Func, _Config) -> P1 = code:purge(nif_mod), @@ -222,6 +223,18 @@ eq_cmp_do(A,B) -> end, ok. + +many_args(doc) -> ["Test NIF with many arguments"]; +many_args(suite) -> []; +many_args(Config) when is_list(Config) -> + ?line ensure_lib_loaded(Config ,1), + ?line ok = apply(?MODULE,many_args_100,lists:seq(1,100)), + ?line ok = many_args_100(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100), + ok. + + + + neg(doc) -> ["Negative testing of load_nif"]; neg(suite) -> []; neg(Config) when is_list(Config) -> @@ -271,6 +284,7 @@ type_test() -> ?nif_stub. tuple_2_list(_) -> ?nif_stub. is_identical(_,_) -> ?nif_stub. compare(_,_) -> ?nif_stub. +many_args_100(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. nif_stub_error(Line) -> exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 0d5ed6e28f..4532062dce 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -289,6 +289,20 @@ static ERL_NIF_TERM compare(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) return enif_make_int(env, enif_compare(env,argv[0],argv[1])); } +static ERL_NIF_TERM many_args_100(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + int i, k; + if (argc == 100) { + for (i=1; i<=100; i++) { + if (!enif_get_int(env,argv[i-1],&k) || k!=i) { + goto badarg; + } + } + return enif_make_atom(env,"ok"); + } +badarg: + return enif_make_badarg(env); +} static ErlNifFunc nif_funcs[] = { @@ -300,7 +314,8 @@ static ErlNifFunc nif_funcs[] = {"type_test", 0, type_test}, {"tuple_2_list", 1, tuple_2_list}, {"is_identical",2,is_identical}, - {"compare",2,compare} + {"compare",2,compare}, + {"many_args_100", 100, many_args_100} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload) -- cgit v1.2.3