Отказ от ответственности: автор вопроса имеет среднее знание Erlang и базовые знания C.
Теперь я читаю Руководство пользователя по совместимости. Я успешно скомпилировал пример complex.c
, и он без проблем работает с портом Erlang.
Однако я хотел бы понять, как работает фактический код C. Я понимаю это в целом: в примере он считывает 2 байта со стандартного ввода и проверяет первый байт. В зависимости от первого байта он вызывает функцию foo
или bar
. Это предел моего понимания этого прямо сейчас.
Итак, если взять оба 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);
}
и 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);
}
}
Что там делает каждая функция? Какую цель действительно выполняют переменные li, len, i, wrote, got
?
Еще несколько мелких вопросов:
- Почему функции не имеют типов возврата, даже
void
s? - Когда порт Erlang отправляет данные на C, первый байт определяет вызываемую функцию. Если байт содержит десятичное число 1, тогда вызывается
foo()
, если байт содержит десятичную дробь 2, тогда вызываетсяbar()
. Если это не изменилось, этот протокол можно использовать для вызова до 255 различных функций C только с одним параметром. Это правильно? - "Добавление индикатора длины будет выполняться автоматически через порт Erlang, но должно выполняться явно во внешней программе C". Что это значит? На какой строке кода это делается?
- Из учебника: "По умолчанию программа C должна считывать со стандартного ввода (дескриптор файла 0) и записывать на стандартный вывод (дескриптор файла 1)". Затем: "Обратите внимание, что stdin и stdout предназначены для буферизованного ввода/вывода и не должны использоваться для связи с Erlang!" Какая уловка здесь?
- почему
buf
инициализируется[100]
?