aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2015-12-10 11:28:56 +0100
committerLukas Larsson <[email protected]>2016-04-15 14:53:09 +0200
commit13bd4ca2493d8a76f9d835c27163b56ba86c2aef (patch)
tree777ed6f8c7062ee79bcb7f0afa17b565de9aa39a
parentfa2f841dc17da2704c2307b6f04aaee85de2366d (diff)
downloadotp-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.c45
-rw-r--r--erts/emulator/beam/erl_nif.h2
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;