[erlang-questions] Static callback in NIF
Fri Jul 1 17:18:37 CEST 2016
The only legit way to create an ErlNifEnv is to call enif_alloc_env().
I bet the compiler warned about your static ErlNifEnv
just before you went hunting for erts internal header files :-)
In OTP-19.0 the 'msg_env' argument to enif_send() can be NULL
in which case the message will be copied and you can reuse
the environment for the next message with enif_clear_env().
This is effective if the message is small.
On 06/30/2016 08:31 PM, Igor Clark wrote:
> Thanks Daniel, good to hear.
> Thanks also Roger & Sergej for your replies. I'll try out
> enif_alloc_env()'ing a new ErlNifEnv each time the callback uses
> enif_send(), rather than just leaving it static.
> On 30/06/2016 07:45, Daniel Goertzen wrote:
>> Static vs priv_data are functionally the same here so it doesn't
>> matter which way you go. I can empathize with your sense of dread;
>> there are a lot of rules to keep track of for keeping Undefined
>> Behavior at bay. But you seem to have a good handle on things.
>> On Thu, Jun 30, 2016 at 6:02 AM Igor Clark <igor.clark@REDACTED
>> <mailto:igor.clark@REDACTED>> wrote:
>> Hi folks,
>> I've got a NIF that uses some library code to talk to specific
>> It's a hobby project with only one user (me) and no real performance
>> concerns, so what I've got works well at the moment, but I think I'm
>> doing some sneaky/dirty stuff and would like to know the best way
>> to do
>> what I need.
>> Sending messages outwards from erlang->C->HW is easy, very quick,
>> works fine. I return a pointer to the HW reference back to erlang
>> the enif_*_resource functions, and manage keeping track of
>> everything on
>> the erlang side, which feels pretty natural.
>> Coming the other way works fine too, but relies on a C function
>> which gets called when the hardware has a message for me. Right
>> now I
>> just have a static function in the NIF C code which I pass to the
>> library. I create a static ErlNifEnv on NIF load() which I keep
>> and use in the callback to send messages to a specified erlang Pid,
>> passed in via enif_get_local_pid() in another NIF function and also
>> stored statically. This works a treat, but I'm feeling some pretty
>> strong dread that it's very much the wrong way to do things, and
>> for scheduler headaches/explosions.
>> I'm planning to try storing the various resources in priv_data at
>> time, on the theory that that way the memory would at least be
>> by the NIF system rather than just as enif_alloc()'ing static
>> but I'm not sure if that would make any diffrence if code
>> external to
>> the scheduler calls back into it.
>> I've looked into running this part as a C node or a port that sends
>> messages with the HW data in a callback in its own process, and the
>> communication seems straightforward enough, but it also seems like I
>> immediately need to start designing mechanisms to deal with
>> working out
>> where to send received messages, almost a protocol in itself.
>> with the NIF+callback method I have a lot of the work done for me -
>> except, of course, for the synchronisation and memory management,
>> is the bit I'm worried about.
>> FWIW the callback code doesn't modify any of the static data
>> directly, it just calls library code which uses the stored
>> references to
>> work out which hardware device & channel to send the message to.
>> What's the best practice here? Is a callback in a NIF OK if it's
>> in priv_data, or is it never OK? What's the best way to do this if
>> Would appreciate any tips!
>> erlang-questions mailing list
>> erlang-questions@REDACTED <mailto:erlang-questions@REDACTED>
> erlang-questions mailing list
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the erlang-questions