wxErlang Hello World
This blog post assumes that you have Erlang installed with wxWidgets support enabled, as this comes by default.
One of the things I like to do is to explore all the mysteries that OTP has bundled by default, and one of those things is wxErlang.
wxWidgets
But first, let’s talk about wxWidgets. wxWidgets is a GUI C++ library that allows developers to create applications that are cross-platform compatible. It was started in 1992 by Julian Smart. It’s object-oriented and has bindings for several programming languages, including Erlang.
wxErlang
It’s a binding for wxWidgets that OTP includes by default when installing Erlang. It’s used for applications like :observer
and :debugger
.
wxErlang is functional instead of object-oriented, and the events are managed as messages to processes. It allows multiple Erlang processes to handle the same application. The only drawback is that we need to do manual memory handling. This means destroying objects after using them.
Hello World in Erlang
It’s an Erlang library, so it seems fitting to start with an example in Erlang. For that, let’s start an Erlang Emulator or erl
session
> erl
and type the following:
1> wx:new().
{wx_ref,0,wx,[]}
2> M = wxMessageDialog:new(wx:null(), "Hello World").
{wx_ref,35,wxMessageDialog,[]}
3> wxMessageDialog:showModal(M).
5100
4> wxMessageDialog:destroy(M).
ok
Don’t you love the dots at the end of each line?! But enough of Erlang! This is an Elixir blog post.
Hello World in Elixir
We’ll write the same program but this time in iex
instead of erl
using Elixir.
So, fire up an iex session
> iex
and type:
1> :wx.new()
{:wx_ref, 0, :wx, []}
2> m = :wxMessageDialog.new(:wx.null(), 'Hello World')
{:wx_ref, 35, :wxMessageDialog, []}
3> :wxMessageDialog.showModal(m)
5100
4> :wxMessageDialog.destroy(M)
ok
Great! We got a message dialog with the text “Hello World”. Let’s dig deeper into what we are doing
1> :wx.new()
This line creates an environment and memory mapping with wxWidgets and needs to be called once per application at the beginning. It stores a reference in the current process, you can see it by doing Process.info(self())
and looking for the wx_env
key.
2> m = :wxMessageDialog.new(:wx.null(), 'Hello World')
And this creates a new MessageDialog
object with the text “Hello World”. You had probably noticed that we are passing a charlist instead of a binary. This is because Erlang uses charlist instead of binaries as strings. :wx.null()
tells the message box that this element doesn’t have a parent, it’s a top level element.
3> :wxMessageDialog.showModal(m)
The previous line created the message box object, but we need to call showModal
to make it visible.
4> :wxMessageDialog.destroy(M)
Lastly, after we close the message box, we need to destroy the object to reclaim the memory. Remember that this is a C++ library.
Some real examples of wxErlang
wxErlang demo
:wx.demo()
Erlang/OTP observer app
:observer.start()
Erlang/OTP debugger app
:debugger.start
You can find other examples here.
Conclusion
This was just a quick introduction to wxErlang. Now you know that this binding exists and comes by default with OTP. Applications like :observer
and :debugger
use it for their UI. In a next post, we’ll dig deeper into how to use wxErlang to create more complex applications.