diff options
author | Lukas Larsson <[email protected]> | 2015-12-10 11:28:56 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2016-04-15 14:53:09 +0200 |
commit | 13bd4ca2493d8a76f9d835c27163b56ba86c2aef (patch) | |
tree | 777ed6f8c7062ee79bcb7f0afa17b565de9aa39a | |
parent | fa2f841dc17da2704c2307b6f04aaee85de2366d (diff) | |
download | otp-13bd4ca2493d8a76f9d835c27163b56ba86c2aef.tar.gz otp-13bd4ca2493d8a76f9d835c27163b56ba86c2aef.tar.bz2 otp-13bd4ca2493d8a76f9d835c27163b56ba86c2aef.zip |
erts: Add erts_nif_get_funcs and erts_nif_call_function
These are convinience functions for calling nifs from erts
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 45 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.h | 2 |
2 files changed, 46 insertions, 1 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 1f5793f534..61dba4ef82 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -2960,6 +2960,51 @@ void erl_nif_init() resource_type_list.name = THE_NON_VALUE; } +int erts_nif_get_funcs(struct erl_module_nif* mod, + ErlNifFunc **funcs) +{ + *funcs = mod->entry->funcs; + return mod->entry->num_of_funcs; +} + +Eterm erts_nif_call_function(Process *p, struct erl_module_nif* mod, + ErlNifFunc *fun, int argc, Eterm *argv) +{ + Eterm nif_result; +#ifdef DEBUG + /* Verify that function is part of this module */ + int i; + for (i = 0; i < mod->entry->num_of_funcs; i++) + if (fun == mod->entry->funcs+i) + break; + ASSERT(i < mod->entry->num_of_funcs); + if (p) + ERTS_SMP_LC_ASSERT(erts_proc_lc_my_proc_locks(p) & ERTS_PROC_LOCK_MAIN); +#endif + if (p) { + struct enif_environment_t env; + ASSERT(is_internal_pid(p->common.id)); + erts_pre_nif(&env, p, mod); + env.may_delay_enif_send = 1; + nif_result = (*fun->fptr)(&env, argc, argv); + if (env.exception_thrown) + nif_result = THE_NON_VALUE; + erts_post_nif(&env); + } else { + /* Nif call was done without a process context, + so we create a phony one. */ + struct enif_msg_environment_t msg_env; + setup_nif_env(&msg_env, mod); + msg_env.env.may_delay_enif_send = 1; + nif_result = (*fun->fptr)(&msg_env.env, argc, argv); + if (msg_env.env.exception_thrown) + nif_result = THE_NON_VALUE; + enif_clear_env(&msg_env.env); + } + + return nif_result; +} + #ifdef USE_VM_PROBES void dtrace_nifenv_str(ErlNifEnv *env, char *process_buf) { diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index 44a2581436..33785ecaca 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -96,7 +96,7 @@ typedef enum { struct enif_environment_t; typedef struct enif_environment_t ErlNifEnv; -typedef struct +typedef struct enif_func_t { const char* name; unsigned arity; |