ndreynolds / ex_termbox

Low-level termbox bindings for Elixir
MIT License
55 stars 14 forks source link

ExTermbox in escript #3

Open qhwa opened 4 years ago

qhwa commented 4 years ago

Hi, I'm trying to make a command-line app with Ratatouille and ExTermbox and having a lot of fun of it.

So far everything works fine in iex, and mix run, but in an escript.

When running the escript binary, I got error messages like this:

13:58:42.454 [warn]  The on_load function for module Elixir.ExTermbox.Bindings returned:
{:error, :bad_name}

** (EXIT from #PID<0.98.0>) shutdown: failed to start child: Ratatouille.Window
    ** (EXIT) an exception was raised:
        ** (UndefinedFunctionError) function ExTermbox.Bindings.init/0 is undefined (module ExTermbox.Bindings is not available)
            (ex_termbox 1.0.2) ExTermbox.Bindings.init()
            (ratatouille 0.5.1) lib/ratatouille/window.ex:104: Ratatouille.Window.init/1
            (stdlib 3.11) gen_server.erl:405: :gen_server.init_it/2
            (stdlib 3.11) gen_server.erl:373: :gen_server.init_it/6
            (stdlib 3.11) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

FYI, here is a minimum repository to reproduce this issue.

Why does not it work?

In an escript binary, ExTermbox is unable to load the NIF file from its priv dir. This is because priv dir of dependencies are stripped during the escript compilation.

Should we fix it?

I suggest so.

While this is certainly not ExTerbox's fault, and there are other libraries with the same problem too, I think it's a special case for ExTermbox, because ExTermbox IMO is supposed to be used in command-line applications, and CLI applications on Elixir are most likely packed in escripts.

My attempt to fix it

So I took an attempt to solve this problem by changing the way of loading NIF. The idea is to embed NIF binaries into the Elixir module, and generate a temporary file for loading.

I forked and made a proof of concept commit here: https://github.com/qhwa/ex_termbox/commit/971cfe6e726cea81338cb5746dc1f12c0e2dd0fe

and it works. In case you want to see the result, you can check out the embed_nif branch of the example repo to give it a try.

Help needed

Although I got it working as I wished, I need some discussion and your opinions. I wonder if there is a better approach to fix this problem.

Please drop your ideas. :)

iboard commented 2 years ago

I just ran into this issue and wonder if it is on the radar and what are the plans? Is there any other way to run a Ratatouille application in a terminal?

jasonwc commented 2 years ago

I would also love to see this! Currently trying to add a Ratatouille based dashboard in an existing escript CLI tool.