NIF调用Erlang后二进制更改的值

abi*_*ips 4 c erlang erlang-shell c++11 erlang-nif

我打算使用NIF操作二进制文件用于我计划在Erlang中编码的应用程序.下面给出了指向cpp文件的gist链接和NIF的erl文件.

[Erl Gist Link] https://gist.github.com/abhijitiitr/3a5bc97184d6dd32f97b

[C++ Gist Link] https://gist.github.com/abhijitiitr/24d2b780f2cdacebfb07

基本上我正在尝试做一个简单的测试.在NIF调用之间共享二进制文件,并使用连续的NIF调用成功操作它们.

如果你在erlang REPL中测试代码

c(binary_test).
Ref=binary_test:open(<<1>>).
binary_test:increment(Ref,<<3>>).
Run Code Online (Sandbox Code Playgroud)

存储的二进制文件在NIF调用之间发生变化.第三个命令的REPL输出是

1
 3
  60
    60
      <<"?">>
Run Code Online (Sandbox Code Playgroud)

<<1>>在初始化阶段通过了.它为什么改为<<60>>?我无法弄清楚这里发生了什么.有人可以指出错误吗?

C++编译指令

clang++ -std=c++11 -stdlib=libc++ -undefined dynamic_lookup -O3 -dynamiclib binary_test.cpp -o binary_test.so -I /usr/local/Cellar/erlang/17.0/lib/erlang/erts-6.0/include/ 
Run Code Online (Sandbox Code Playgroud)

在我的Mac上.

此外,我想问一下在NIF中操作共享资源的并发进程.这是可能的还是有一个规则,即必须在单个Erlang进程中访问NIF.

Ste*_*ski 5

您遇到问题是因为您非法访问内存.在你的BinaryStore构造函数中,你试图从传递给的参数列表中保存二进制文件binary_test:open/1,但是这不起作用,因为一旦NIF调用完成它们就会释放这些参数.您需要保存参数的副本以便以后使用它.要执行此操作,请先向您的BinaryStore班级添加新成员:

    ErlNifEnv* term_env;
Run Code Online (Sandbox Code Playgroud)

接下来,修改构造函数以进行分配term_env,然后使用它来复制传入的术语:

    BinaryStore(ERL_NIF_TERM binary)
    {
        term_env = enif_alloc_env();
        binary_term = enif_make_copy(term_env, binary);
    }
Run Code Online (Sandbox Code Playgroud)

这将binary_termterm_env环境中分配,然后将传入的术语复制到其中.你还需要一个析构函数来释放term_env:

    ~BinaryStore()
    {
        enif_free_env(term_env);
    }
Run Code Online (Sandbox Code Playgroud)

最后,您需要传递term_env而不是在函数中env检查binary_termincrement_binary:

    nifpp::get_throws(term_env, binary_term, ibin);
Run Code Online (Sandbox Code Playgroud)

通过这些修改,我从运行代码得到以下结果:

1> Ref=binary_test:open(<<1>>).
Reading symbols for shared libraries . done
<<>>
2> binary_test:increment(Ref,<<3>>).
1
 3
  1
   1
    <<4>>
Run Code Online (Sandbox Code Playgroud)

(顺便说一下,你应该使用"\r\n"行结尾而不是仅仅"\n"在从Erlang模拟器内部打印时使用,以便换行总是返回到最左边的列.)

您仍然有一个问题,即泄漏分配的内存new_bin2.

我对学习NIF细节的建议是避免使用像nifpp最初那样的包,因此您可以学习NIF API以及有关内存所有权,资源分配和释放以及参数转换的所有详细信息.一旦你了解它们,使用类似的包nifpp变得更容易和更有成效.