How do I get the char*
data from an ERL_NIF_TERM
coming from an Elixir binary string?
I see term_to_binary/1
function but it does not seem to be the right thing.
How do I get the char*
data from an ERL_NIF_TERM
coming from an Elixir binary string?
I see term_to_binary/1
function but it does not seem to be the right thing.
As it’s stated in NIF
documentation
Terms of type binary are accessed with the help of struct type
ErlNifBinary
, which contains a pointer (data
) to the raw binary data and the length (size
) of the data in bytes. Both data and size are read-only and are only to be written using calls to API functions. Instances ofErlNifBinary
are, however, always allocated by the user (usually as local variables).
That said, your NIF
function should have a signature alongside
static ERL_NIF_TERM
foo(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
where argc
is supposed to be 1
, argv[0]
would be a constant pointer to ErlNifBinary
and the respective elixir call would be like
def foo(binary), do: :erlang.nif_error("Load NIF!")
While using NIF, you have to use charlist and NOT Elixir binary Strings. Use to_charlist/1
function to convert binary string to charlist and then call the NIF function.
In the NIF function, you can read charlist like so,
#define MAXBUFLEN 1024
char src[MAXBUFLEN];
enif_get_string(env, argv[0], src, MAXBUFLEN, ERL_NIF_LATIN1);
src
now holds the string value.
You first need to prepare ErlNifBinary
and then populate it using enif_inspect_binary()
.
According to NIF doc, ErlNifBinary
is a struct with two visible fields like below.
typedef struct {
size_t size;
unsigned char* data;
} ErlNifBinary;
data
is the char*
you want. enif_inspect_binary()
fills ErlNifBinary
with information about the binary, making its data accessible.
Assuming that the binary string is the first argument of your nif function, the C code should look something like this.
static ERL_NIF_TERM
do_stuff_with_binary(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
unsigned char data[100];
ErlNifBinary bin;
if (!enif_inspect_binary(env, argv[0], &bin)) {
return enif_make_atom(env, "error");
}
// Do stuff with binary. Its data is now accessible via bin.data
// memcpy(data, bin.data, 100);
return enif_make_atom(env, "ok");
}