customized ERL_NIF_TERM type support

Daniel Goertzen <[email protected]> Fri, 7 Feb 2014 11:34:14 -0600
Newsgroups gmane.comp.lang.erlang.patches
Message-ID <CAJCf5RxSjiO4jRKngbToPWyyWwXQz2Vbu5niqQquDda1Wd-FgA@mail.gmail.com>
When writing NIFs in C++, it is impossible to employ C++ function
overloading because the underlying type of ERL_NIF_TERM is "unsigned int".
For example:

// won't compile :(
#include <erl_nif.h>
void my_func(ERL_NIF_TERM a)  {...}
void my_func(unsigned int a)  {...}


This patch allows NIF authors to mutate the type of ERL_NIF_TERM by
defining the macro CUSTOM_NIF_TERM_TYPE().  In the example below, the
underlying unsigned integer type gets wrapped as a C++11 typed
enumeration.  The type of ERL_NIF_TERM is now unique and can be used in
overloaded functions.

// compiles!  :)
#define CUSTOM_NIF_TERM_TYPE(Type) enum class ERL_NIF_TERM : Type {};
#include <erl_nif.h>
void my_func(ERL_NIF_TERM a)  {...}
void my_func(unsigned int a)  {...}


The patch has no impact on erl_nif.h if CUSTOM_NIF_TERM_TYPE is not defined
(other than flipping the definition order of ERL_NIF_TERM and ERL_NIF_UINT).

A similar approach has been used on my C++11 NIF wrapper (
https://github.com/goertzenator/nifpp).  The wrapper requires manual
installation of a similar patch, and I would love to remove that
requirement.

Regards,
Dan.

_______________________________________________
erlang-patches mailing list
[email protected]
http://erlang.org/mailman/listinfo/erlang-patches
custom_erl_nif_term.patch (text/x-patch, 889 B)
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index 7613446..e6d7ca6 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -93,17 +93,21 @@ #endif
 
 #ifdef HALFWORD_HEAP_EMULATOR
 #  define ERL_NIF_VM_VARIANT "beam.halfword" 
-typedef unsigned int ERL_NIF_TERM;
+typedef unsigned int ERL_NIF_UINT;
 #else
 #  define ERL_NIF_VM_VARIANT "beam.vanilla" 
 #  if SIZEOF_LONG == SIZEOF_VOID_P
-typedef unsigned long ERL_NIF_TERM;
+typedef unsigned long ERL_NIF_UINT;
 #  elif SIZEOF_LONG_LONG == SIZEOF_VOID_P
-typedef unsigned long long ERL_NIF_TERM;
+typedef unsigned long long ERL_NIF_UINT;
 #  endif
 #endif
 
-typedef ERL_NIF_TERM ERL_NIF_UINT;
+#ifdef CUSTOM_NIF_TERM_TYPE
+CUSTOM_NIF_TERM_TYPE(ERL_NIF_UINT)
+#else
+typedef ERL_NIF_UINT ERL_NIF_TERM;
+#endif
 
 struct enif_environment_t;
 typedef struct enif_environment_t ErlNifEnv;