Erlang Port drivers and Erl_interface
Robert Raschke
rrerlang@REDACTED
Thu Jan 27 15:09:47 CET 2005
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
More information about the erlang-questions
mailing list