const erl = @cImport({ @cInclude("erl_nif.h"); }); pub export fn hello(env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const erl.ERL_NIF_TERM) erl.ERL_NIF_TERM{ _ = argv; _ = argc; //const ERL_NIF_LATIN1 = @as(c_uint, 1); return erl.enif_make_string(env, "Hello world!", 1); // ERL_NIF_LATIN1); } pub export fn factorial(env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const erl.ERL_NIF_TERM) erl.ERL_NIF_TERM{ if(argc != 1){ return erl.enif_make_badarg(env); } var n: c_long = undefined; if(erl.enif_get_long(env, argv[0], &n) == 0 or n < 0){ return erl.enif_make_badarg(env); } if(n > 34){ // max n for max factorial for u128 return erl.enif_make_tuple2(env, erl.enif_make_atom(env, "error"), erl.enif_make_string(env, "input too large, max is 34", 1) ); } var result: u128 = 1; var i = @as(u128, @intCast(n) ); //var i = n; while(i > 1) : (i -= 1){ result *= i; } var num_bytes: usize = 1; var temp = result; while(temp > 255) : (temp >>= 8){ num_bytes += 1; } var bin: erl.ErlNifBinary = undefined; // for return binary in big-endian if(erl.enif_alloc_binary(num_bytes, &bin) == 0){ return erl.enif_make_badarg(env); // alloc faild } temp = result; var idx = num_bytes; while(idx > 0) : (idx -= 1){ bin.data[idx - 1] = @as(u8, @intCast(temp & 0xFF) ); temp >>= 8; } return erl.enif_make_binary(env, &bin); } const nif_funcs = [_]erl.ErlNifFunc{ .{ .name = "hello", .arity = 0, .fptr = hello, .flags = 0, }, .{ .name = "factorial", .arity = 1, .fptr = factorial, .flags = 0, }, }; export fn nif_init() ?*erl.ErlNifEntry{ return &nif_entry; } var nif_entry: erl.ErlNifEntry = .{ .major = 2, .minor = 16, .name = "niftest", .num_of_funcs = nif_funcs.len, .funcs = @constCast(&nif_funcs), .load = null, .reload = null, .upgrade = null, .unload = null, .vm_variant = "beam.vanilla", .options = 1, // 0, .sizeof_ErlNifResourceTypeInit = @sizeOf(erl.ErlNifResourceTypeInit), .min_erts = "erts-12.0", // .entry_version = 3, };