2

我是 Erlang 爱好者和新手 Erlang Prorammer。

我最近不得不面对 Erlang 中的数据处理问题。因此,我决定使用 NIF。我有两个 proplists 列表,我必须根据一个术语返回两个 proplists 的哈希连接。

为了实现它,我决定学习 C 中的二进制操作。此外,我正在使用 nifpp 库(C++11)来简化我的学习体验。来源:https ://github.com/goertzenator/nifpp

以下是我能想到的用于提取二进制文件并将其复制到另一个有据可查的 ErlNifBinary 的代码。但我无法操纵它。

ErlNifBinary ebin, bin_term;
nifpp::get_throws(env, argv[0], ebin); // Assigns ebin to the input binary
enif_alloc_binary(16, &bin_term); // Size of new binary
memcpy(bin_term.data, ebin.data, ebin.size); // Copying the contents of binary

我在 bin_term.data 中有一个指向 unsigned char 的指针。如何更改 bin_term.data 中的内容?

此外,如果我返回现有的复制二进制文件,我会为相同的输入获得不同的输出,并且考虑到我刚刚处理了来自输入的数据这一事实,并且不等于输入。 return enif_make_binary(env, &bin_term);

在 erlang REPL 中,如果我使用参数 <<7>> 或任何其他二进制文件执行函数,我得到的结果为 <<7,127,128,29,0,0,0,0,1,0,0,0,24 ,1,0,0>> 或一些随机动态值。有人可以指出代码中的错误是什么。

4

1 回答 1

3

首先,当您初始化时bin_term,您使用的是静态16字节大小。这就是为什么你的函数总是返回比预期大的二进制(16 位,如果你计算的话)。所以你可以做的第一件事就是bin_term使用从 Erlang 传递的二进制文件的大小创建

enif_alloc_binary(16, &bin_term); // Constant size

enif_alloc_binary(ebin.size, &bin_term); // Same size as binary from Erlang

并且在调用nifppErlNifBinary 上有一个包装器,您可以使用它简单地编写bianry

binary bin_term = new binary(ebin.size);

甚至添加您自己的复制构造函数。

其次,这是访问二进制数据。如果您查看如何ErlNifBinary定义,您可以看到所有数据都可以通过data字段访问(就像您预期的那样),该字段是指针unsigned char(换句话说,数组的长度由size字段给出)。

因此,如果您想例如增加并打印此二进制文件中的每个值,您可以执行以下操作

ErlNifBinary ebin, bin_term;
nifpp::get_throws(env, argv[0], ebin); // Assigns ebin to the input binary
enif_alloc_binary(ebin.size, &bin_term); // Size of new binary
memcpy(bin_term.data, ebin.data, ebin.size); // Copying the contents of binary

for(int i=0; i<bin_term.size; ++i){
    bin_term.data[i] = bin_term.data[i] + 1;
    std::cout << bin_term.data[i] << std::endl;
}

如果您需要除字符数组(原始内存)之外的其他数据表示形式,您可以查看Resource 对象,这些对象本质上是指向 C 内存的智能指针(垃圾收集),可以在 Erlang 中传递。

于 2014-09-28T12:38:31.620 回答