免责声明:该问题的作者具有Erlang的平均知识和C的基本知识。
我正在阅读Interoperability Tutorial User Guide。我已经成功编译了complex.c
示例,它可以在没有任何问题的情况下使用Erlang端口。
但是,我想了解实际的C代码是如何工作的。我一般都理解它:在示例中,它从标准输入读取2个字节并检查第一个字节。根据第一个字节,它调用foo
或bar
函数。这是我现在对它的理解的极限。
所以,如果我们同时采用{{1}}:
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
s?void
,如果该字节包含小数2,则调用foo()
。如果不改变,无论如何这个协议可用于调用多达255个不同的C函数,每个函数只有1个参数。是吗?bar()
被初始化为buf
?答案 0 :(得分:6)
这个答案同样被放弃了(我不是Erlang或C程序员,我恰好经历了相同的材料)
你的初始模型有点偏。代码实际工作的方式是从stdin
读取前两个字节,假设它表示实际消息的长度,然后从stdin
读取更多字节。在这种特定情况下,实际消息总是两个字节(一个对应于一个函数的数字和一个传递给它的单个整数参数)。
0 - a) read_exact
从len
读取stdin
字节,read_cmd
首先使用read_exact
来确定字节数它应该读取(由前两个字节表示的数字,如果可用的字节少于两个,则为none),然后读取那么多字节。 write_exact
将len
个字节写入stdout
,write_cmd
使用write_exact
输出一个两字节长度的标头,然后输出适当长度的消息(希望如此)。
0 - b)我认为上面已充分涵盖了len
。 li
是用于为写入函数生成该双字节头的变量的名称(我不能逐步引导您完成位移操作,但最终结果是len
表示在发送的前两个字节中)。 i
是一个中间变量,其主要目的似乎是确保write
和read
不返回错误(如果有,则返回错误代码作为{的结果{1}} / read_exact
)。 write_exact
和wrote
跟踪已写入/读取的字节数,包含的循环在大于got
之前退出。
1 - 我其实不确定。我使用的版本是len
类型,但其他方面相同。我从Programming Erlang的第12章开始,而不是你链接的指南。
2 - 这是正确的,但端口协议的要点是您可以更改它以发送不同的参数(如果您发送任意参数,它会最好只使用C Node方法而不是端口)。作为一个例子,我在最近的一段中modified it subtly,因此它发送一个字符串,因为我只有一个我想在C侧调用的函数,因此无需指定函数。我还要提一下,如果你的系统需要调用超过255个用C语言编写的不同操作,你可能需要重新考虑它的结构(或者只是整个九个并用C语言写出来)。
3 - 这已经完成
int
在read_cmd(byte *buf)
{
int len;
if (read_exact(buf, 2) != 2) // HERE
return(-1); // HERE
len = (buf[0] << 8) | buf[1]; // HERE
return read_exact(buf, len);
}
函数和
read_cmd
write_cmd(byte *buf, int len)
{
byte li;
li = (len >> 8) & 0xff; // HERE
write_exact(&li, 1); // HERE
li = len & 0xff; // HERE
write_exact(&li, 1); // HERE
return write_exact(buf, len);
}
函数中的。我认为解释见write_cmd
;这是一个标题告诉/发现消息的其余部分将是多长时间(是的,这意味着它只能是一个有限长度,并且该长度必须以两个字节表示)。
4 - 我不完全确定为什么这会是一个问题。注意详细说明?
5 - 0 - a)
是一个字节数组,必须明确限制(出于内存管理的目的,我认为)。我在这里将“buf
”视为“比我们计划容纳的最大邮件大小更大的数字”。选择的实际数字似乎是任意的,似乎任何4或更高的数字都可以,但我可以在这一点上得到纠正。