使用ei_encode_string对字符串进行编码

时间:2016-05-05 01:59:54

标签: c++ erlang

我开始使用ei库在我的c程序中编码,然后将该编码数据传递给我的erlang客户端。我知道我可以使用binary_to_term / 1来获取erlang中的数据。

在发送到套接字之前,我很难尝试对数据进行编码。顺便说一句,我已建立联系。

  int index = 0;
  const char *buff = "Stackoverflow";
  char p[strlen(buff) + 1];
  ei_encode_string_len(p, &index, buff, strlen(buff))

输入是buff,第三个参数。 p是我希望编码字符串的输出缓冲区。

但数据未被编码并放入输出缓冲区

我尝试通过遍历每个字符来打印输出缓冲区,并且可以看到107正在打印,其中ETF表示字符串但不确定为什么整个字符串未被编码。

我有什么遗失的吗?

谢谢!

感谢您的帮助!

1 个答案:

答案 0 :(得分:4)

您的代码很好,除了您用来编码的缓冲区太小。

首先,让我们看看使用"Stackoverflow"转换术语term_to_binary获得的二进制文件:

1> Term = term_to_binary("Stackoverflow").
<<131,107,0,13,83,116,97,99,107,111,118,101,114,102,108,
  111,119>>

第一个字节131是该术语的版本幻数;让我们暂时忽略它。第二个字节107表示编码数据的类型,正如您在问题中已解释的那样。

接下来,让我们使用以下代码(类似于您的代码)来查看由ei_encode_string_len创建的数据:

int index = 0;
const char *buff = "Stackoverflow";
char p[strlen(buff) + 3];
memset(p, 0, sizeof p);
ei_encode_string_len(p, &index, buff, strlen(buff));
for (int i = 0; i < sizeof p; ++i)
    printf("%d ", (unsigned char)p[i]);
printf("\n");

编译并运行此结果会产生以下输出:

  

107 0 13 83 116 97 99 107 111 118 101 114 102 108 111 119

需要注意的一点是,在此代码中,缓冲区p比代码中的两个额外字节大。这是因为编码缓冲区的第二个和第三个字节 - 这里分别保存值013 - 是一个两字节的大端值,用于编码字符串长度,13个字节。我们可以在Erlang中轻松看到这个长度:

2> length("Stackoverflow").
13

这两个字节后面是字符串数据,我们也可以使用Erlang看到它们的值:

3> [C || C <- "Stackoverflow"].
[83,116,97,99,107,111,118,101,114,102,108,111,119]

ei_encode_string_len完全匹配,这些也与我们在term_to_binary生成的二进制文件中看到的相同。

最后,回到版本幻数:它必须是任何编码术语中的第一个字节。要将其放入缓冲区,请在编码任何实际数据之前使用ei_encode_version

int index = 0;
const char *buff = "Stackoverflow";
char p[strlen(buff) + 4];
memset(p, 0, sizeof p);
ei_encode_version(p, &index);
ei_encode_string_len(p, &index, buff, strlen(buff));
for (int i = 0; i < sizeof p; ++i)
    printf("%d ", (unsigned char)p[i]);
printf("\n");

请注意,我们已将p的大小增加1个字节以保存版本幻数。编译并运行此代码会生成以下值,该值与term_to_binary给出的值完全匹配:

  

131 107 0 13 83 116 97 99 107 111 118 101 114 102 108 111 119

请注意,您可以使用ei_x_...函数变量进行编码来避免这些缓冲区大小调整问题,因为它们使用的动态缓冲区会根据需要调整大小。