我开始使用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表示字符串但不确定为什么整个字符串未被编码。
我有什么遗失的吗?
谢谢!
感谢您的帮助!
答案 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
比代码中的两个额外字节大。这是因为编码缓冲区的第二个和第三个字节 - 这里分别保存值0
和13
- 是一个两字节的大端值,用于编码字符串长度,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_...
函数变量进行编码来避免这些缓冲区大小调整问题,因为它们使用的动态缓冲区会根据需要调整大小。