Slide 1

Slide 1 text

NIFs in MoDern Languages Ryo Kajiwara, 4/27/2018 @ RubyxElixirConf Taiwan 2018

Slide 2

Slide 2 text

Self-Intro Ryo Kajiwara (ֿݪ ཾ) the IDIOT (ID + IoT) engineer Twitter: @s01

Slide 3

Slide 3 text

Elixir Web Framework developed by ACCESS, releasing today! Make your own PaaS

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

TL;DR

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

meets

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Okay, actually what • Played around with NIFs(Native Implemented Functions) in Dlang • Implemented SHA-3 (esp. SHA3-256) in D, called from Elixir • one of NIFs' important use is cryptographic libraries

Slide 10

Slide 10 text

NIFs are dangerous • When NIFs fail, the whole VM dies • So, we want to write NIFs in a relatively "safer" language • One of the more popular options is Rust, which is supported by Rustler • Using ports is a safer way to interact with foreign languages

Slide 11

Slide 11 text

Why Dlang? • Fast execution • Memory management made simpler • Dynamic arrays • No pointers until you really need it • Strong compile-time metaprogramming

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

Okay, Let's Start Playing With Fire

Slide 14

Slide 14 text

Code at: github.com/sylph01/ nifs_in_d (code is not intended for production)

Slide 15

Slide 15 text

How to compile {_result, _errcode} = System.cmd("dmd", [ "native_lib/sha3_d.d", "-c", "-fPIC", "-of=native_obj/sha3_d.o" ], stderr_to_stdout: true) • -c: Compile only • -fPIC: Position-independent-code

Slide 16

Slide 16 text

How to compile {_result, _errcode} = System.cmd("g++", [ "native_lib/sha3.cpp", "native_obj/sha3_d.o", "-fPIC", "-shared", "-L/home/sylph01/.asdf/installs/dmd/2.079.1/dmd2/linux/lib64", "-I/home/sylph01/.asdf/installs/erlang/20.3.4/usr/include", "-lphobos2", "-pthread", "-o", "native_obj/sha3.so" ], stderr_to_stdout: true) (Paths can be omitted when included in env vars)

Slide 17

Slide 17 text

Example 1: Simple Add extern (C++) int add(int a, int b){ return a + b; } Here we use C++ as the interface between D and Erlang.

Slide 18

Slide 18 text

Example 1: Simple Add ERL_NIF_TERM add_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]){ int a = 0; int b = 0; if (!enif_get_int(env, argv[0], &a)) { return enif_make_badarg(env); } if (!enif_get_int(env, argv[1], &b)) { return enif_make_badarg(env); }

Slide 19

Slide 19 text

Example 1: Simple Add int result = add(a, b); return enif_make_int(env, result); } The function does: • Extract integer value from ERL_NIF_TERM • Call the function in D • Then make an ERL_NIF_TERM with the result

Slide 20

Slide 20 text

Example 1: Simple Add ErlNifFunc nif_funcs[] = { {"add", 2, add_nif} }; int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { rt_init(); return 0; } ERL_NIF_INIT(Elixir.Add, nif_funcs, load, NULL, NULL, NULL);

Slide 21

Slide 21 text

Example 2: SHA-3 extern (C++) immutable(char)* sha3_256_c(const char *s) { import std.string; return toStringz(toHex(sha3_256(fromStringz(s)))); } Different from Example 1: we are getting a string = binary in Erlang world

Slide 22

Slide 22 text

Example 2: SHA-3 inside sha3_256_nif: ERL_NIF_TERM term; unsigned char* ret = enif_make_new_binary(env, 64, &term); ... return term; } • Make a ERL_NIF_TERM, and assign a char* to indicate its binary content

Slide 23

Slide 23 text

Example 2: SHA-3 if (!enif_inspect_iolist_as_binary(env, argv[0], &input)){ return enif_make_badarg(env); } memcpy(ret, sha3_256_c(reinterpret_cast(input.data)), 64); • Extract binary from ERL_NIF_TERM argv[0] • Then use its data to call sha3_256_c, copy its value to ret

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

c93d30bc856...d96edb matches!

Slide 27

Slide 27 text

Thoughts • Tons of boilerplate • Why use D when C++ is used as interface? • Increases boilerplate even more... • Variable-length lists in D are hard to leverage when C++ is interfacing • Next: Explore possibilities of direct NIFs in D?

Slide 28

Slide 28 text

Feedbacks welcome! GitHub: sylph01/nifs_in_d Twitter: @s01