[erlang-questions] calling FUN from NIF
Scott Lystig Fritchie
fritchie@REDACTED
Tue Sep 13 23:29:20 CEST 2011
Paul Davis <paul.joseph.davis@REDACTED> wrote:
pd> On the other hand, there are planned enhancements to the NIF api to
pd> allow such awesomeness. See Rickard's talk at [1].
If you can't wait for that kind of awesomeness, I *know* that it's
possible to do what you're looking for via a driver instead of a NIF.
(Because I saw some of Tony Rogvall's driver code from a decade ago to
it. :-) With a bit of enginuity, perhaps the technique could also be
applied to NIFs.
Note: this is just a sketch from memory poisoned by a lot of
intervening time. Also note that the Erlang process that makes the
initial call to the driver is the samem process that executes the
driver's Erlang callback function, i.e., PID <a.b.c>.
This is a mash-up attempt to show that time flows as you read from
top to bottom. Note that the way this is sketched, the driver can
request more than one callback be executed on the Erlang side of the
world.
Erlang code C code in driver
Erlang process <a.b.c> Deep in the virtual machine
---------------------- ---------------------------
drv_command(Port,
SerializedCommandData)
driver's struct erl_drv_entry.outputv
function(): calculate stuff, decides
that it needs to call an Erlang
callback function, sends reply to
request a callback function call.
Store intermediate state in driver's
private data.
%% Code path on first call:
%% driver sends us ?WantCallback
get_port_answer(Port) ->
receive
{Port, {data, [Response|Rest]=_Data}} ->
case Response of
?WantCallback ->
{M, F, As} = decode_callback_request(Rest),
Answer = erlang:apply(M, F, As),
% Encode answer and send it back to
% driver via drv_command() or whatever
get_port_answer(Port);
?FinalAnswer ->
% Decode and return to caller
decode_final_answer(Rest)
end
end.
Erlang send us an encoded callback
reply. Decode the reply, fetch our
intermediate state out of my private
data, and continue calculating.
[...] Ah, I'm done, so I reply with my
final answer.
%% This time, get_port_answer()
%% will receive a message with
%% ?FinalAnswer tag.
-Scott
More information about the erlang-questions
mailing list