6 ms·
Zigler: Zig NIFs in Elixir
- lionkor 2y agoCompletely lacking a description that made it clear, but basically, from what I can tell, this lets you embed Zig code inside Elixir code
- G4BB3R 2y agoAre sigils (~) restricted to one char? To me seems ~Zig would be more clear and short enough.
- Miner49er 2y agoErlang sigils are not, they can be any length, limited to characters allowed in atoms. Elixir sigils also allow multiple characters in the name, but chars after the first must be upper case, according to the docs. So for Elixir, it would have to be something like ~zIG
- throwawaymaths 2y agoAccording to the docs, must be all upper case: > Custom sigils may be either a single lowercase character, or an uppercase character followed by more uppercase characters and digits. https://hexdocs.pm/elixir/sigils.html https://hexdocs.pm/elixir/sigils.html
- Miner49er 2y agoAh yeah, you're right.
- Muromec 2y agoWait, erlang has sigils?
- com 2y agoYeah, there’s a bit of a developer experience push going on in erlang world, which is great!
- psychoslave 2y agoGreat! But, what is a nifs, please? :'D
- jameskilton 2y agoNatively Implemented Functions https://www.erlang.org/doc/system/nif.html https://www.erlang.org/doc/system/nif.html
- sangnoir 2y agoIt's Elixir's[1] equivalent of a Foreign Function Interface. 1. More accurately, NIFs sre BEAM's take on FFI functions, and Elixir is a BEAM language.
- kuon 2y agoI use zig a lot in elixir nif, for things like audio and video processing, it works great. But I do not use zigler as I prefer the code to live in their own codebases. But zigler is really nice and it provides an easy way to do computational heavy tasks in elixir.
- kansi 2y ago> I use zig a lot in elixir nif, for things like audio and video processing Sounds interesting, is it open source? I am interested in seeing how the code layout looks like when mixing Zig and Elixir
- kuon 2y agoI don't have open source code base to share but here it how it looks like: // the_nif.zig fn init_imp( env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const erl.ERL_NIF_TERM, ) !erl.ERL_NIF_TERM { if (argc != 0) { return error.BadArg; } return try helpers.make("Hello world"); } export fn media_tools_init( env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const erl.ERL_NIF_TERM, ) erl.ERL_NIF_TERM { return init_imp(env, argc, argv) catch |err| return helpers.make_error(env, err); } var funcs = [_]erl.ErlNifFunc{ erl.ErlNifFunc{ .name = "init", .arity = 1, .fptr = media_tools_init, .flags = erl.ERL_NIF_DIRTY_JOB_CPU_BOUND, } }; var entry = erl.ErlNifEntry{ .major = erl.ERL_NIF_MAJOR_VERSION, .minor = erl.ERL_NIF_MINOR_VERSION, .name = "Elixir.MediaTools.Stream", .num_of_funcs = funcs.len, .funcs = &funcs, .load = load, .reload = null, .upgrade = null, .unload = null, .vm_variant = "beam.vanilla", .options = 0, .sizeof_ErlNifResourceTypeInit = @sizeOf(erl.ErlNifResourceTypeInit), .min_erts = "erts-10.4", }; export fn nif_init() *erl.ErlNifEntry { return &entry; } # the_exlixir_file.ex assert "Hello world" == MediaTools.Stream.init() The "helpers" library is used to convert types to and from erlang, I plan on open sourcing it but it is not ready now. In the above example, the code is explicit but "entry" can be created with an helper comptime function. erl is simply the erl_nif.h header converted by zig translate-c. I wrote a piece back in 2022, but things evolved a lot since then: https://www.kuon.ch/post/2022-11-26-zig-nif/ https://www.kuon.ch/post/2022-11-26-zig-nif/
- ihumanable 2y agoFor anyone mystified about what a NIF is that doesn't want to go read the docs. The BEAM VM (which is the thing that runs erlang / elixir / gleam / etc) has 3 flavors of functions. - BIFs - Built-in functions, these are written in C and ship with the VM - NIFs - Natively implemented functions, these are written in any language that can speak the NIF ABI that BEAM exposes and allows you to provide a function that looks like a built-in function but that you build yourself. - User - User functions are written in the language that's running on BEAM, so if you write a function in erlang or elixir, that's a user function. NIFs allow you to drop down into a lower level language and extend the VM. Originally most NIFs were written in C, but now a lot more languages have built out nice facilities for writing NIFs. Rust has Rustler and Zig now has Zigler, although people have been writing zig nifs for a while without zigler and I'm sure people wrote rust nifs without rustler.
- hinkley 2y agoIt’s important to note that while Erlang has protections against user code crashing an Erlang process and recovering, a faulty NIF can take down the entire virtual machine.
- alberth 2y agoHence why Rustler is of so much interest since it provides more protections against this happening. Discord is a big Erlang + Rustler user.
- derefr 2y agoDoes anyone actually enjoy using these systems that encourage you to embed programming-language X code in programming-language Y heredocs? I always find actually doing that — and then maintaining the results over time — to be quite painful: you don't get syntax highlighting inside the string; you can no longer search your worktree reliably using extension-based filtering; etc. I personally find the workflow much more sane if/when you just have a separate file (e.g. `foo.zig`) for the guest-language code, and then your host-language code references it.
- systems 2y agoI initially agree But, if all you do is write elixir wrappers around the zig function, to completely hide the foreign language functions, keeping both the wrapper and implementation in the same file, even if two different languages doesn't seem horrible, but again, keeping them in two file doesn't seem like a huge difference too I think its really a matter of taste, both options viable
- toast0 2y agoI've done some assembly in C, and for big functions, yeah, I want it in its own file, but smaller things often make sense to embed. I'm not sure if I'd like my nif code embedded into my erl files (assuming this works for Erlang as well), but it could conceivably make the nasty bit of boilerplate around ERL_NIF_INIT in the NIF (which I have to do in C anyway) and exit(nif_library_not_loaded) in the erl go away, which would be nice. It's certainly possible to get syntax highlighting on the embedded code, but you'll need to work with your syntax highlighter; it certainly helps if you're not the only person using it. But then again, I worked without syntax highlighting for years, so I'm happy when it works, but when it doesn't, I'm ok with that too.
- harrisi 2y agoSyntax highlighting here can work correctly, actually. Also, I'm not sure why it's not better documented in Zigler, but you can also write the code in a separate file just fine.
- h0l0cube 2y ago
- harrisi 2y agoZig is also used in an excellent way by burrito[0]. I've also used zig for compiling NIFs written in C/C++/Objective-C, since `zig cc` makes cross-compiling much nicer. I wish zig got more use and attention in the Erlang ecosystem, but rustler seems more popular.
- kansi 2y ago[0] https://github.com/burrito-elixir/burrito https://github.com/burrito-elixir/burrito
- OkayPhysicist 2y agoRustler is more popular because Rust solves one of the scarier bits about NIFs, the fact that irresponsible memory management in a NIF can kill the entire Erlang VM. I can appreciate Zig for entire projects that would otherwise be written in C, but for the lengths of code that make sense for a NIF as opposed to a port, Zig seems like a strange point of failure to add to my system. If it's simple enough that I can be confident in my flawless manual memory management, I'd just use C, and for anything else, Rust is the far safer choice.
- nine_k 2y ago(Yo dawg, we put a niche language into a niche language so that...) I wonder if the Zig code can be not written inline, as an option. With anything larger than a few lines, I'd want syntax highlighting, LSP support, navigation, etc. It's easier to achieve with one language per file.
- harrisi 2y agoYes, you can put Zig code in a separate file.
- Dowwie 2y agoUnderstand NIF risks: they can crash your entire Elixir Application, beyond their immediate supervision tree, because they operate in the same memory space as the BEAM itself. NIF responsibly. :)
- rkangel 2y agoIsn't the "cimport" stuff in Zig going away at some point? Making this somewhat less useful.
- deleted 2y ago[deleted]
- tayloramurphy 2y agoThis is an incredibly off-topic, but hopefully a fun fact for folks here. There was a popular motivational speaker in the 80's and 90's named Zig Ziglar[0]. He was influential on Tony Robbins and his career. Just shows even how a randomly generated name [1] may not be so unique! [0] https://en.wikipedia.org/wiki/Zig_Ziglar https://en.wikipedia.org/wiki/Zig_Ziglar [1] https://en.wikipedia.org/wiki/Zig_(programming_language)#Origin_of_the_name https://en.wikipedia.org/wiki/Zig_(programming_language)#Ori...