How to import constants from Erlang header file?

Hi all,

How can I import the constants from a shared and mutable “.hrl” file at runtime?

Erlang “.hrl” file:

-define(X, valx).
-define(Y, valy).
|> Enum.filter(&String.starts_with(&1, "-define("))

Roughly like this.

But why is that file “mutable”? In my opinion the proper way where to have a single erlang module that imports those defines and exposes them as functions…


Heh, that’s more of a hack than a proper solution. @fun2src you can define an erlang module in src/ and have functions inside that return the constants. This will not impose a meaningful performance penalty since the constants will still be part of the constants memory space.

1 Like

Well, he explicitely asked for reading a mutable file at runtime, therefore I started with the hack, suggesting to use exactly the way you describe as well…

1 Like

Ah, I missed the runtime bit. That does pose a bit of an issue! I think I might still opt for reading and evaling the erlang file at runtime even since then it isn’t up to me to sort out what to do with the -define string. Regardless I think we’re in agreement that the runtime part of this is odd, @fun2src can you elaborate on that part?

The file is generated and read by Erlang applications (in production) to which I do not have access. I can only access the “.hrl” file in the shared directory. The file mutates four times a day.

So it would be something like this:

init([]) ->
  {ok, erlang:send_after(1, self(), check_hrl_file)}.

handle_info(check_hrl_file, CurrentTimer) ->
  {noreply, erlang:send_after(2.16e+7, self(), check_hrl_file)}.

and the suggestion (@NobbZ):

def load_list_of_constants(path) do
  |> Enum.filter(&String.starts_with(&1, "-define("))

I would like to know what is the difference (in terms of efficiency) between

the proper way where to have a single erlang module that imports those defines and exposes them as functions…


|> Enum.filter(&String.starts_with(&1, “-define(”))

Could I implement the proper way using hot code swapping?

mv file.hrl path/elixir-app/src

Thank you so much! @NobbZ @benwilson512

It would be better to use :epp_dodger.parse_file/1:

with {:ok, forms} <- :epp_dodger.parse_file(file) do
  for {:tree, :attribute, _, {_, {:atom, _, :define}, [{_, _, name}, {_, _, value}]}} <- forms,
    do: {name, value}

Beautiful @hauleth. Thank you! :smile:

1 Like

Great discussion, I’m struggling with using the humongous wx.hrl in my Elixir project and have been using this .ex module so far:

So I do like the idea of just parsing “wx.hrl” at runtime but it has some expressions on the right hand of the define that make my curious about your implementation of parse_and_extract_values

Here some examples from wx.hrl:

-define(wxGA_VERTICAL, ?wxVERTICAL).
-define(wxDialog_ButtonSizerFlags, (?wxOK bor ?wxCANCEL bor ?wxYES bor ?wxNO bor ?wxHELP bor ?wxNO_DEFAULT)).

Anyone has a lib that can handle all of these?