Erlang Port drivers and Erl_interface
casper2000a@REDACTED
casper2000a@REDACTED
Thu Jan 27 16:49:49 CET 2005
Hi Robert,
This is really good information. Thanks a lot.
Have you used Port Driver call back functions outputv, event, etc. I have 2 concerns about them.
Unfortunately the documentation I found on them are not enough to absorb the full working scenario
of them.
1) In outputv, the erlang emulator sends the message as a ErlIOVec. I wonder how I can use
ei_decode to extract the message.
2) I didn't find a good document on event call back function. What're the information pass in as
ErlDrvEvent and ErlDrvEventData?
3) Have you used anync or enq/deq functions in Port Driver? If you can give me some help or sample
would be excellent.
4) Please confirm you are discussing above a Port driver, but not a C Node or Erl_Interface based
port.
5) In your below example, in which call back functions can you call handle_regular_message to
decode the function? Could you provide an example call back function.
Thanks in advance!
Eranga
Quoting Robert Raschke : > Quoting Robert Raschke :
> Hi Eranga,
>
> you wrote:
> > Let\'s say I want to pass a complex structure back and forth. And I opened
> > the linked-in driver port using binary. Then can I use term_to_binary and
> > binary_to_term in the Erlang side and erl_decode, erl_encode and other erl
> > interface functions in the C side?
>
> I have been using the term_to_binary and binary_to_term functions as
> well. In my C port program I use the ei_decode...() and
> ei_encode...() functions. It took me a little bit to get used to the
> way these functions handle the message buffer, but with a little bit
> of experimentation you will get up and running quickly.
>
> For example I send my requests from erlang in a predefined format
> (obviously), and then I unpack it in my C program like this, with the
> x_in buffer holding a message. It is very verbose, as I was learning
> how the ei functions work while writing it.
>
> static void
> handle_regular_message(ei_x_buff *x_in, ei_x_buff *x_out)
> {
> int valid = 1;
> int version;
> int arity;
> char call_atom[MAXATOMLEN];
> erlang_pid from;
> char fn_atom[MAXATOMLEN];
>
> /*
> Incoming message has to be
> {call, Caller_Pid, Fn, [Params]}
> with
> call - the atom \'call\'
> Caller_Pid - erlang pid of process that sent the message
> Fn - name as atom of the function to invoke
> Params - parameters to pass to Fn
>
> For an invalid request message the return message has the form
> {error, badmsg}
>
> For a valid request message the return message has the form
> {Caller_Pid, Result}
> with
> Result = ok | {ok, Value} | {error, internal, error} | {error, badarg,
> args}
> */
>
> if (valid && ei_decode_version(x_in->buff, &x_in->index, &version) != 0) {
> fprintf(stderr, \"Warning: Ignoring received malformed message (bad
> version).\\n\");
> valid = 0;
> }
>
> if (valid && ei_decode_tuple_header(x_in->buff, &x_in->index, &arity) != 0)
> {
> fprintf(stderr, \"Warning: Ignoring received malformed message (not
> tuple).\\n\");
> valid = 0;
> }
> if (valid && arity != 4) {
> fprintf(stderr, \"Warning: Ignoring received malformed message (not 4-arity
> tuple).\\n\");
> valid = 0;
> }
>
> if (valid && ei_decode_atom(x_in->buff, &x_in->index, call_atom) != 0) {
> fprintf(stderr, \"Warning: Ignoring received malformed message (first tuple
> element not atom).\\n\");
> valid = 0;
> }
> if (valid && strcmp(call_atom, \"call\") != 0) {
> fprintf(stderr, \"Warning: Ignoring received malformed message\"
> \" (first tuple element not atom \'call\').\\n\");
> valid = 0;
> }
>
> if (valid && ei_decode_pid(x_in->buff, &x_in->index, &from) != 0) {
> fprintf(stderr, \"Warning: Ignoring received malformed message (Second tuple
> element not pid).\\n\");
> valid = 0;
> }
>
> if (valid && ei_decode_atom(x_in->buff, &x_in->index, fn_atom) != 0) {
> fprintf(stderr, \"Warning: Ignoring received malformed message (Third tuple
> element not atom).\\n\");
> valid = 0;
> }
>
> if (valid) {
> x_out->index = 0;
> ei_x_encode_version(x_out);
> ei_x_encode_tuple_header(x_out, 2);
> ei_x_encode_pid(x_out, &from);
>
> fprintf(stderr, \"Attempting to call e_%s().\\n\", fn_atom);
>
> if (strcmp(fn_atom, \"my_fun_1\") == 0) my_fun_1(x_in, x_out);
> else if (strcmp(fn_atom, \"my_fun_2\") == 0) my_fun_2(x_in, x_out);
> else if (strcmp(fn_atom, \"my_fun_3\") == 0) my_fun_3(x_in, x_out);
> else {
> fprintf(stderr, \"Warning: Ignoring received malformed message\"
> \" (Third tuple element not recognised function).\\n\");
> valid = 0;
> }
> if (valid) {
> fprintf(stderr, \"Returned from my_fun().\\n\");
> }
> }
>
> if (! valid) {
> x_out->index = 0;
> ei_x_encode_version(x_out);
> ei_x_encode_tuple_header(x_out, 2);
> ei_x_encode_atom(x_out, \"error\");
> ei_x_encode_atom(x_out, \"badmsg\");
> }
> }
>
> Each function I invoke (my_fun()) takes apart the rest of the x_in
> buffer, and completes the result buffer x_out (which gets sent back to
> Erlang).
>
> I hope this gets you further along,
> Robby
>
>
--------------This mail sent through OmniBIS.com--------------
More information about the erlang-questions
mailing list