Disclaimer: The author of the question has an average knowledge of Erlang and a basic knowledge of C.
I am reading the Interoperability Tutorial User Guide now. I have successfully compiled the complex.c
example and it works with the Erlang Port without any problems.
However, I would like to understand how the actual C code works. I understand it in general: in the example it reads 2 bytes from the standard input and checks the first byte. Depending on the first byte it calls either foo
or bar
function. This is the limit of my understanding of it right now.
So, if we take both erl_comm.c
:
/* erl_comm.c */
typedef unsigned char byte;
read_cmd(byte *buf)
{
int len;
if (read_exact(buf, 2) != 2)
return(-1);
len = (buf[0] << 8) | buf[1];
return read_exact(buf, len);
}
write_cmd(byte *buf, int len)
{
byte li;
li = (len >> 8) & 0xff;
write_exact(&li, 1);
li = len & 0xff;
write_exact(&li, 1);
return write_exact(buf, len);
}
read_exact(byte *buf, int len)
{
int i, got=0;
do {
if ((i = read(0, buf+got, len-got)) <= 0)
return(i);
got += i;
} while (got<len);
return(len);
}
write_exact(byte *buf, int len)
{
int i, wrote = 0;
do {
if ((i = write(1, buf+wrote, len-wrote)) <= 0)
return (i);
wrote += i;
} while (wrote<len);
return (len);
}
and port.c
:
/* port.c */
typedef unsigned char byte;
int main() {
int fn, arg, res;
byte buf[100];
while (read_cmd(buf) > 0) {
fn = buf[0];
arg = buf[1];
if (fn == 1) {
res = foo(arg);
} else if (fn == 2) {
res = bar(arg);
}
buf[0] = res;
write_cmd(buf, 1);
}
}
What does each function actually do there? What purpose do li, len, i, wrote, got
variables actually serve?
Some more small questions:
- Why do not the functions have any return types, even
void
s? - When Erlang port sends data to C, the first byte determines a function to be called. If the byte holds the decimal 1, then
foo()
is called, if the byte holds the decimal 2, thenbar()
is called. If not changed anyhow this protocol can be used to call up to 255 different C functions with only 1 parameter each. Is that right? - "Adding the length indicator will be done automatically by the Erlang port, but must be done explicitly in the external C program". What does that mean? On which line of code is it done?
- From the Tutorial: "By default, the C program should read from standard input (file descriptor 0) and write to standard output (file descriptor 1)." Then: "Note that stdin and stdout are for buffered input/output and should not be used for the communication with Erlang!" What is the catch here?
- why
buf
is initialized to[100]
?