[erlang-patches] customized ERL_NIF_TERM type support

Daniel Goertzen <>
Mon Feb 10 20:28:43 CET 2014


Regarding C++ types in extern "C":  That is a very good question...

I looked into the C++ standard and other documents.  The answer is that
extern "C"  just changes the default linkage to "C" instead of "C++".
 Everything else remains the same, so you can still use the rest of C++
inside an extern "C", but the linkage may impose some limitations (like no
function overloading).  "C" linkage names only indicate the name the of the
function but not the parameter or return types like C++ linkage names.

Now that I am a little more educated on linking and calling conventions, I
am uncomfortable with the patches I have suggested.  Sure, they work on
linux with gcc, but will they work on MSVC?  What about the other less
common unices?  I think depending on linker looseness is brittle.

As an alternate idea, I think I can generate inline C++ wrappers for the
whole NIF API and get a unique ERL_NIF_TERM type that way.  It's not very
elegant, but everything gets resolved at compile time with no linker
tricks, and the compiler should flatten the wrapper away so that there is
no overhead.

So, if you agree, I'd like to take this patch out back and shoot it. :)

Dan.






On Mon, Feb 10, 2014 at 7:09 AM, Sverker Eriksson <
> wrote:

> The "hook" solution has an advantage I think. It leaves it up to the user
> to define the type and thereby to "make it work".
>
> I actually don't understand how you get this to work. How can you mix C++
> types within a extern "C" declaration?
>
> /Sverker
>
>
> On 02/07/2014 08:21 PM, Daniel Goertzen wrote:
>
>> Thank you for your feedback.  Maybe the "hook" approach I suggested is too
>> generic.  My original patch from nifpp actually looks like this...
>>
>> #ifdef CPP11_UNIQUE_TERM_TYPE
>>    enum class ERL_NIF_TERM : ERL_NIF_UINT;
>> #else
>>    typedef ERL_NIF_UINT ERL_NIF_TERM;
>> #endif
>>
>> ...and then to use the typed enum in your c++ nif you write...
>>
>> #define CPP11_UNIQUE_TERM_TYPE
>> #include <erl_nif.h>
>>
>>
>> In the future ERL_NIF_TERM can be changed to a struct and the
>> CPP11_UNIQUE_TERM_TYPE option can just be ignored.  What do you think?
>>
>> Cheers,
>> Dan.
>>
>>
>> On Fri, Feb 7, 2014 at 12:46 PM, Sverker Eriksson <
>> > wrote:
>>
>>    Thanks for the patch.
>>>
>>> I got one objection/question though. My C++ knowledge is a bit rusty but
>>> as I understand it
>>> the "enum class" construct demands that Type is an integer type.
>>>
>>> This is currently true for ERL_NIF_TERM but it might not be in the
>>> future.
>>> I earlier tried to define ERL_NIF_TERM as
>>>
>>> typedef struct { int x; } ERL_NIF_TERM;
>>>
>>> to get stronger type checking even for C. I reverted that due to bad
>>> performance
>>> as gcc has different calling conventions for int and struct {int}.
>>> However, future compilers
>>> might be better at passing struct{int} by value in which case we might
>>> want to change
>>> the definition of ERL_NIF_TERM.
>>>
>>> What then? Do we ignore CUSTOM_NIF_TERM_TYPE in such a scenario?
>>>
>>>
>>> /Sverker, Erlang/OTP
>>>
>>>
>>>
>>> On 02/07/2014 06:34 PM, Daniel Goertzen wrote:
>>>
>>> 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 ://
>>> erlang.org/mailman/listinfo/erlang-patches
>>>
>>>
>>>
>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-patches/attachments/20140210/21b987c9/attachment.html>


More information about the erlang-patches mailing list