首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C和Erlang: Erlang端口示例

C和Erlang: Erlang端口示例
EN

Stack Overflow用户
提问于 2012-05-07 20:06:14
回答 1查看 3K关注 0票数 8

免责声明:该问题的作者对Erlang的平均知识和对C.

我现在正在读互操作性教程用户指南。我已经成功地编译了complex.c示例,它与Erlang一起工作,没有任何问题。

但是,我想了解实际的C代码是如何工作的。我一般理解它:在示例中,它从标准输入中读取2个字节,并检查第一个字节。根据第一个字节的不同,它调用foobar函数。这就是我现在对它的理解的极限。

所以,如果我们同时取两个erl_comm.c

代码语言:javascript
复制
/* 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

代码语言:javascript
复制
/* 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 变量的实际用途是什么?

一些更小的问题:

  1. 为什么函数没有任何返回类型,甚至是void
  2. 当Erlang端口向C发送数据时,第一个字节确定要调用的函数。如果字节包含小数点1,则调用foo(),如果字节包含小数点2,则调用bar()。如果不改变,则可以使用该协议调用255个不同的C函数,每个函数只有一个参数。是那么回事吗?
  3. 添加长度指示符将由Erlang端口自动完成,但必须在外部C程序中显式执行。那是什么意思?它是在哪一行代码上完成的?
  4. 在本教程中:“默认情况下,C程序应该从标准输入(文件描述符0)读取并写入标准输出(文件描述符1)。”然后:“注意,stdin和stdout用于缓冲输入/输出,不应用于与Erlang的通信!”这里的陷阱是什么?
  5. 为什么buf初始化为[100]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-05-08 02:00:52

同样,这个答案也被拒绝了(我不是Erlang或C程序员,我只是碰巧经历了相同的材料)

你的初始型号有点离谱。代码的实际工作方式是从stdin读取前两个字节,假设它表示实际消息的长度,然后从stdin读取更多的字节。在这种特殊情况下,实际消息总是两个字节(对应于函数的数字和传递给它的单个整数参数)。

0 - a) read_exactstdin读取len字节,read_cmd首先使用read_exact来确定它应该读取多少字节(一个由前两个字节表示的数字,或者如果可用字节少于两个字节,则没有一个字节),然后再读取这几个字节。write_exactlen字节写入stdoutwrite_cmd使用write_exact输出两个字节长度的头,然后是适当长度的消息(希望如此)。

0 - b)我认为len在上面有足够的介绍。li是用于为写函数生成两个字节头的变量的名称(我不能一步一步地引导您完成位移位操作,但是最终的结果是len用发送的前两个字节表示)。i是一个中间变量,其主要目的似乎是确保writeread不返回错误(如果它们返回了错误,那么错误代码将作为read_exact/write_exact的结果返回)。wrotegot跟踪写入/读取了多少字节,包含的循环在大于len之前退出。

1 -实际上我不确定.我所使用的版本是int类型的,但在其他方面是相同的。我是从编程二郎的第12章中得到的,而不是你链接的指南。

2 -是正确的,但端口协议的要点是您可以将其更改为发送不同的参数(如果您发送任意参数,最好只使用C节点方法而不是端口)。例如,我在最近的一段中使用巧妙地修改它来发送单个字符串,因为我只想在C端调用一个函数,这样就不需要指定一个函数了。我还应该提到,如果您有一个系统需要调用超过255个用C编写的不同操作,那么您可能需要重新考虑它的结构(或者只需要用C编写全部九个操作)。

3 -这是完成的

代码语言:javascript
复制
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函数和

代码语言:javascript
复制
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函数中。我认为0 - a)中包含了这个解释;这是一个标头,它告诉/发现消息的其余部分将是多长时间(是的,这意味着它只能是一个有限的长度,并且该长度必须以两个字节表示)。

4 -我不完全确定为什么这会是一个陷阱.介意详细说明一下吗?

5 - buf是一个字节数组,必须显式限定(为了内存管理目的,我认为)。我在这里将"100“读为”大于我们计划容纳的最大消息大小的数字“。实际选择的数字似乎是任意的,似乎任何4或更高的数字都可以,但我可以在这一点上得到纠正。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10488388

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档