Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C NIF调用Erlang后二进制值的更改_C_C++11_Erlang_Erlang Shell_Erlang Nif - Fatal编程技术网

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

C NIF调用Erlang后二进制值的更改,c,c++11,erlang,erlang-shell,erlang-nif,C,C++11,Erlang,Erlang Shell,Erlang Nif,我打算使用NIFs为我计划在Erlang中编写的应用程序操作二进制文件。 下面给出了NIF的cpp文件和erl文件的主要链接 [Erl要点链接] [C++要点链接] 基本上我在做一个简单的测试。跨NIF调用共享二进制文件,并通过连续的NIF调用成功地操作它们 如果您在erlang REPL中测试代码 c(binary_test). Ref=binary_test:open(<<1>>). binary_test:increment(Ref,<<3>>

我打算使用NIFs为我计划在Erlang中编写的应用程序操作二进制文件。 下面给出了NIF的cpp文件和erl文件的主要链接

[Erl要点链接]

[C++要点链接]

基本上我在做一个简单的测试。跨NIF调用共享二进制文件,并通过连续的NIF调用成功地操作它们

如果您在erlang REPL中测试代码

c(binary_test).
Ref=binary_test:open(<<1>>).
binary_test:increment(Ref,<<3>>).
在我的Mac电脑上


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

ERL\u NIF\u TERM
s必须与
ErlNifEnv
关联,并且传递给NIF函数的env仅在该函数调用期间有效。当您将一个术语存储到
BinaryStore
对象中,然后从另一个nif调用中使用它时,您就违反了这个规则。您的选择:

  • 为二进制存储创建一个新的ErlNifEnv,并将nif调用中的术语复制到这个新的env中

  • > P>使用C++数据结构(如代码> STD::vector < /代码>)来存储二进制数据。我想这对你的情况来说会更简单


    您遇到问题是因为您非法访问内存。在
    BinaryStore
    构造函数中,您试图从传递给
    binary\u test:open/1
    的参数列表中保存二进制文件,但这不起作用,因为一旦NIF调用完成,这些参数就会被释放。您需要保存参数的副本,以便以后使用。为此,首先向
    BinaryStore
    类添加一个新成员:

        ErlNifEnv* term_env;
    
    接下来,修改构造函数以分配
    术语\u env
    ,然后使用它复制传入术语:

        BinaryStore(ERL_NIF_TERM binary)
        {
            term_env = enif_alloc_env();
            binary_term = enif_make_copy(term_env, binary);
        }
    
    这将在
    term\u env
    环境中分配
    binary\u term
    ,然后将传入的术语复制到其中。您还需要一个析构函数来释放
    term\u env

        ~BinaryStore()
        {
            enif_free_env(term_env);
        }
    
    最后,在
    increment\u binary
    函数中检查
    binary\u term
    时,需要传递
    term\u env
    而不是
    env

        nifpp::get_throws(term_env, binary_term, ibin);
    
    通过这些修改,我可以从运行代码中获得以下结果:

    1> Ref=binary_test:open(<<1>>).
    Reading symbols for shared libraries . done
    <<>>
    2> binary_test:increment(Ref,<<3>>).
    1
     3
      1
       1
        <<4>>
    
    1>Ref=binary\u测试:open()。
    读取共享库的符号。完成
    2> 二进制测试:增量(参考,)。
    1.
    3.
    1.
    1.
    
    (顺便说一下,从Erlang emulator内部打印时,您应该使用
    “\r\n”
    行结尾,而不仅仅是
    “\n”
    ,以便换行符始终返回到最左边的列。)

    您还有一个问题,那就是您泄漏了为
    new\u bin2
    分配的内存


    关于学习NIFs的详细信息,我的建议是首先避免使用像
    nifpp
    这样的包,这样您就可以了解和了解有关内存所有权、资源分配和释放以及参数转换的所有详细信息。一旦你理解了它们,使用像
    nifpp
    这样的软件包就会变得更简单、更有效。

    什么是“二进制”?你是说“一个整数”吗?二进制是一种本机Erlang类型,可以包含任何类型。例如,,。从本质上讲,您可以将其视为ByteString类型的东西。NIF和资源可能同时被多个进程使用,但线程安全的责任在您身上。谢谢。明白了,谢谢你的解释。使用
    nifpp
    的原因基本上是为了编写简洁的代码,
    nifpp
    我认为,一旦没有任何指向资源的引用,就会释放分配给
    new_bin2
    的内存,我认为资源在分配后会被破坏,如果通过
    C
    Api调用,它应该被破坏。如果我错了,请纠正我。但对于
    new\u bin2
    ,您只需通过
    enif\u alloc\u binary
    为其分配内存,然后使用
    memcpy
    将内存复制到其中。没有涉及它的
    nifpp
    调用。因此,在退出
    increment\u binary
    函数之前,需要对其调用
    enif\u release\u binary
    。或者,完全摆脱
    new\u bin2
    ,只需使用
    ibin
    代替它,因为不需要复制
    ibin
    来使用它的值。谢谢,我明白你的意思。关于
    ibin
    ,我想我只能访问
    ibin
    值,不能修改它。正确,您不能更改
    ibin
    。但是用它来代替
    new\u bin2
    是非常好的,因为1)
    new\u bin2
    只是
    ibin
    的一个副本,2)您使用
    new\u bin2
    只是为了读取,而不是写入。
        nifpp::get_throws(term_env, binary_term, ibin);
    
    1> Ref=binary_test:open(<<1>>).
    Reading symbols for shared libraries . done
    <<>>
    2> binary_test:increment(Ref,<<3>>).
    1
     3
      1
       1
        <<4>>