From 13bd4ca2493d8a76f9d835c27163b56ba86c2aef Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas.larsson@erlang-solutions.com>
Date: Thu, 10 Dec 2015 11:28:56 +0100
Subject: erts: Add erts_nif_get_funcs and erts_nif_call_function

These are convinience functions for calling nifs from erts
---
 erts/emulator/beam/erl_nif.c | 45 ++++++++++++++++++++++++++++++++++++++++++++
 erts/emulator/beam/erl_nif.h |  2 +-
 2 files changed, 46 insertions(+), 1 deletion(-)

(limited to 'erts/emulator')

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;
-- 
cgit v1.2.3