Skip to content

Instantly share code, notes, and snippets.

@GoNZooo
Created December 5, 2019 19:58
Show Gist options
  • Save GoNZooo/1e69b8bdd293b625ba7d75d9ccca1efb to your computer and use it in GitHub Desktop.
Save GoNZooo/1e69b8bdd293b625ba7d75d9ccca1efb to your computer and use it in GitHub Desktop.
Segfaulting NIF
// c version:
// #include <erl_nif.h>
// static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
// {
// return enif_make_string(env, "Hello World!", ERL_NIF_LATIN1);
// }
// static ErlNifFunc nif_funcs[] = {"hello", 0, hello};
// ERL_NIF_INIT(Elixir.HelloWorld, nif_funcs, NULL, NULL, NULL, NULL);
const erl = @cImport({
@cInclude("erl_nif.h");
});
export fn hello(env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const c_ulong) erl.ERL_NIF_TERM {
return erl.enif_make_string(env, "Hello World from Zig!", erl.ErlNifCharEncoding.ERL_NIF_LATIN1);
}
// `erl_nif.h` defines this function structure
// typedef struct enif_func_t
// {
// const char* name;
// unsigned arity;
// ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
// unsigned flags;
// }ErlNifFunc;
var nif_funcs = [_]erl.ErlNifFunc{erl.ErlNifFunc{
.name = "hello",
.arity = 0,
.fptr = hello,
.flags = 0,
}};
// This is the `erl_nif.h` entry specification; it's what's actually exported when you use
// `ERL_NIF_INIT(...)`:
// typedef struct enif_entry_t
// {
// int major;
// int minor;
// const char* name;
// int num_of_funcs;
// ErlNifFunc* funcs;
// int (*load) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info);
// int (*reload) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info);
// int (*upgrade)(ErlNifEnv*, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
// void (*unload) (ErlNifEnv*, void* priv_data);
// /* Added in 2.1 */
// const char* vm_variant;
// /* Added in 2.7 */
// unsigned options; /* Unused. Can be set to 0 or 1 (dirty sched config) */
// /* Added in 2.12 */
// size_t sizeof_ErlNifResourceTypeInit;
// /* Added in 2.14 */
// const char* min_erts;
// }ErlNifEntry;
fn makeEntry(
name: [*c]const u8,
functions: c_int,
load: ?fn (*erl.ErlNifEnv, **void, erl.ERL_NIF_TERM) c_int,
) erl.ErlNifEntry {
return erl.ErlNifEntry{
.major = erl.ERL_NIF_MAJOR_VERSION,
.minor = erl.ERL_NIF_MINOR_VERSION,
.name = name,
.num_of_funcs = functions,
.funcs = &nif_funcs,
.load = load,
.reload = null,
.upgrade = null,
.unload = null,
.vm_variant = "beam.vanilla",
.options = 1,
.sizeof_ErlNifResourceTypeInit = @sizeOf(erl.ErlNifResourceTypeInit),
.min_erts = "erts-10.4",
};
}
export fn nif_init() *erl.ErlNifEntry {
return &entry;
}
var entry: erl.ErlNifEntry = makeEntry("Elixir.HelloWorld", 1, null);
// $ zig build-lib --disable-gen-h --library c -I /usr/lib/erlang/usr/include/ --name zig_hello_world -dynamic -fPIC hello_world.zig
// Segmentation fault (core dumped)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment