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