[erlang-patches] customized ERL_NIF_TERM type support

Sverker Eriksson <>
Tue Feb 11 12:33:33 CET 2014


I agree. Shoot!

/Sverker

On 02/10/2014 08:28 PM, Daniel Goertzen wrote:
> 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
>>>>
>>>>
>>>>
>>>>



More information about the erlang-patches mailing list