[erlang-questions] erl_nif: persist binary across calls
Harris, Robert
robert.harris@REDACTED
Fri Feb 8 18:38:59 CET 2019
Hi Sverker,
That worked perfectly.
Many thanks,
Robert
> On 8 Feb 2019, at 15:49, Sverker Eriksson <sverker@REDACTED> wrote:
>
> Hi Robert,
>
> The 'env' you get in 'load' is temporary. Terms created in it will disappear
> when 'load' returns.
> Use enif_alloc_env() to create terms that will survive between NIF calls:
>
> ErlNifEnv* persistent_env;
>
> int load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info)
> {
> persistent_env = enif_alloc_env();
> persistent = create_binary(persistent_env);
> return 0;
> }
>
>
> Use enif_make_copy() to copy terms between ErlNifEnv's:
>
> static ERL_NIF_TERM world_nif(ErlNifEnv* env, ...)
> {
> return enif_make_copy(persistent);
> }
>
> If the persistent binary is large (> 64 bytes) then only a small term header
> will be copied pointing to the binary data.
>
>
> /Sverker
>
> On fre, 2019-02-08 at 14:04 +0000, Harris, Robert wrote:
>> Hi,
>>
>> I am writing a NIF library in which I would like to create persistent binary
>> terms
>> in my load() callback. The purpose of these terms is to act as ready-made
>> keys
>> for frequent calls to enif_get_map_value() in successive calls to other NIFs
>> in the
>> same library.
>>
>> My test case is
>>
>>>
>>> #include <string.h>
>>> #include <erl_nif.h>
>>>
>>> ERL_NIF_TERM persistent;
>>>
>>> static ERL_NIF_TERM
>>> create_binary(ErlNifEnv *env)
>>> {
>>> ErlNifBinary binary;
>>> char *data = "abcdefghijklmnopqrstuvwxyz";
>>> size_t size = strlen(data);
>>>
>>> (void) enif_alloc_binary(size, &binary);
>>> memcpy(binary.data, data, size);
>>> binary.size = size;
>>> return (enif_make_binary(env, &binary));
>>> }
>>>
>>> int
>>> load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info)
>>> {
>>> persistent = create_binary(env);
>>> return (0);
>>> }
>>>
>>> static ERL_NIF_TERM
>>> world_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
>>> {
>>> return (persistent);
>>> }
>>>
>>> static ERL_NIF_TERM
>>> hello_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
>>> {
>>> return (create_binary(env));
>>> }
>>>
>>> static ErlNifFunc nif_funcs[] = {
>>> {"hello", 0, hello_nif},
>>> {"world", 0, world_nif},
>>> };
>>>
>>> ERL_NIF_INIT(hello, nif_funcs, &load, NULL, NULL, NULL)
>> An example of the behaviour I see is
>>
>>>
>>> Erlang/OTP 20 [erts-9.3.3.3] [source] [64-bit] [smp:12:12] [ds:12:12:10]
>>> [async-threads:10] [hipe] [kernel-poll:false]
>>>
>>> Eshell V9.3.3.3 (abort with ^G)
>>> 1>
>>> 1> hello:hello().
>>> <<"abcdefghijklmnopqrstuvwxyz">>
>>> 2> hello:world().
>>> eheap_alloc: Cannot allocate 2305843009213695256 bytes of memory (of type
>>> "heap_frag").
>>>
>>> Crash dump is being written to: erl_crash.dump...done
>>> make: *** [shell] Error 1
>> I'm guessing that what I'm trying is wrong but I'd appreciate a pointer as to
>> why. I'm motivated in part by comments like the following extract from
>> enif_make_new_binary():
>>
>>>
>>> The drawbacks are that the binary cannot be kept between NIF calls and it
>>> cannot
>>> be reallocated.
>> I inferred from this that a binary generated by enif_make_binary() *can* be
>> kept
>> between NIF calls. I'm a newcomer to Erlang, if that's not obvious.
>>
>> Regards,
>>
>> Robert
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> https://urldefense.proofpoint.com/v2/url?u=http-3A__erlang.org_mailman_listinfo_erlang-2Dquestions&d=DwIGaQ&c=L_h2OePR2UWWefmqrezxOsP9Uqw55rRfX5bRtw9S4KY&r=rgvWXjU_2tA1ZUQSslrg0TYOEP4F7UfuySlE3gZm1mQ&m=KpVT9ckjVGBzTRcLi8KyIRtHYE40kNnBV6KUJC9f2cc&s=FGyBxvciQtMGXgbPAmz4GbykgMAb2i_uqS1EuBTNLA8&e=
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> https://urldefense.proofpoint.com/v2/url?u=http-3A__erlang.org_mailman_listinfo_erlang-2Dquestions&d=DwIGaQ&c=L_h2OePR2UWWefmqrezxOsP9Uqw55rRfX5bRtw9S4KY&r=rgvWXjU_2tA1ZUQSslrg0TYOEP4F7UfuySlE3gZm1mQ&m=KpVT9ckjVGBzTRcLi8KyIRtHYE40kNnBV6KUJC9f2cc&s=FGyBxvciQtMGXgbPAmz4GbykgMAb2i_uqS1EuBTNLA8&e=
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3565 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20190208/55b99a25/attachment.bin>
More information about the erlang-questions
mailing list