2014-09-28 92 views
1

我是Erlang爱好者和新手Erlang Prorammer。在C中操作二进制文件NIF Erlang

我最近不得不面对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中的无符号字符的指针。如何更改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 >>或每次一些随机的动态值。有人可以指出代码中的错误吗?

回答

2

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

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

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

而在nifpp有包装上ErlNifBinary called bianry与您可以简单地写

binary bin_term = new binary(ebin.size); 

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

其次,这是访问二进制数据。如果你看如何ErlNifBinary is defined你可以看到所有的数据都可以通过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 objects,它实际上是智能指针(垃圾回收)到您的C内存,可以在Erlang中传递。

+0

非常感谢@mpm。你也可以指导我应该如何存储proplists。 – abips 2014-09-28 13:01:45

+0

说实话,我会尽量不要存储它们。你总是可以将列表和元组翻译为c类型,但是由于proplists可以包含不同长度的元组或单个原子,它们都可能变得非常复杂。如果发送刚才的NIF键列表可能会更容易。或者可能检查[cypto模块](http://erlang.org/doc/man/crypto。html#hash-2),这取决于你的需求([C中的快速哈希](https://github.com/erlang/otp/blob/maint/lib/crypto/c_src/crypto.c))。 – mpm 2014-09-28 17:21:44