Quite awhile ago I wrote a post about learning Python and GTK, unfortunately while I played around with it a bit I never really took to Python. The dynamic typing and the usage of whitespacing as delimiters were not my style. Additionally, I was doing a lot of travel for work at the time and could never really muster the energy at the time to overcome my initial dislike of Python.
So as work slowed down a bit I figured I’d try something new this time. I decided to pick up D due to a number of factors including:
- It’s derived from the C family so has some similarities to Java
- It’s a compiled language so performance is excellent
- Has a garbage collector so again similar to Java.
- And most importantly, has full and up to date bindings for GTK
I had also considered trying Go, but the last point put a bullet in that the available GTK bindings appear to have a ways to go.
So to put the conclusion first, I did end up writing a small utility in D and GTK called Visual Grep. It’s a GTK based GUI for grep that follows Gnome Human Interface Guidelines (HIG) as much as possible. A screenshot is below, if you are interested in trying it out you can find it on Github.
Learning D
I’ve had my eye on D for a number of years as a possible language to use for building GUI applications. The language itself is well designed and as a lot of advantages in the GUI space with safety features such as garbage collection combined with high performance as a compiled language.
Learning the D language itself is relatively straight forward and I didn’t find the learning curve to be that high. Coming from Java, the biggest hurdle was understanding ranges which is core to many features in D. I found it helpful as a starting point to think of ranges as an advanced version of Java’s Iterator class. The other key features in D, such as templates, can be learned over time but Ranges are core to D and need to be understood right up front so I’d recommend dedicating some time to it right at the beginning.
The next aspect of learning D is understanding the standard library called phobos. This library can be thought of as occupying a similar space as the core J2SE libraries. Learning the library and features available is not overly difficult, however the documentation available on dlang can often be overly succint. Additionally, in the Java world if you google on any API you can find a wealth of information, discussion and examples. Since D is much less popular, the amount of resources available is also consequently much less (a theme that will re-occur in subsequent sections).
Having said that, the D community is big enough that questions on forums and the irc channel got answered and I never found myself blocked on any particular issue.
The only issue with D, and reflected in phobos, is the general lack of a library eco-system. In more mainstream environments like Java and Python, there are a plethora of libraries to pretty much cover any use case. Want to create and parse XML, work with PDF files, do localization, interface with USB, etc you have your pick of libraries. In D not so much, while most core functions are available, some key ones are not. For example, there is currently no standard i18n package available for localization, logging is deigned experimental, etc.
This lack of resources is also reflected in phobos itself in terms of implementation and execution. For example, D has an excellent design with respect to multi-threaded communication based on message passing. D also supports the concept of declaring variables as immutable which would seem to be a perfect fit with respect to this message passing. From a design perspective it should work, however due to limitations in the implementation of variants in D you can’t actually use an immutable variable in this scenario. Either you pass a shared variable (D’s way of declaring a variable to be shared among multiple threads) or pass a pointer to the immutable variable and de-reference it on the receive.
Finally the last area of D that I struggled with a bit is pointers. While I have done some work with pointers in the past in Delphi, the usage of pointers in Delphi tended to be very rare. I have to be careful and not exaggerate as by no means is the usage of pointers in D constant need when building GTK apps, it’s just I did find I needed to work with them more then I did in Delphi due to the need to interface with C. Having coded only in Java for the last 12 years, coming back to pointers was a bit of a culture shock.
Learning GTK
My previous experience with GUI frameworks includes Java Swing (hate it) and Delphi VCL (love it).. D has a very complete set of bindings for GTK called GTKD and is highly recommended, Mike Wey does a great job keeping these up to date for each release of GTK. Based on my experiences with Swing and VCL, learning and getting productive with the basics of GTK was very easy with two notable exceptions.
The first is the GTK Treeview which, despite the name, is really an all encompassing listbox/treeview which serves multiple use cases. While it is undeniably powerful, I found it’s API a bit obtuse and difficult to accomplish the basic use cases. The sheer variety of objects related to the TreeView (TreeView, TreeModel, TreePath, TreeIter, CellRenderer, etc) is a bit overwhelming to the newbie.
The other aspect I struggled with a bit was the multi-threading. In GTK, the preferred approach to multi-threading is to setup a callback gdk-threads-add-idle. While not an issue in GTK per se, GTKD does not really give any examples on how best to integrate this with D. Looking at the design though, I went with integrating this with D’s threaded message passing infrastructure and it turned out to work very well but I burned quite a lot of time prototyping and testing to make sure I understood how everything worked.
An invaluable resource for learning GTK and GtkD was the grestful application, an open source D/GtkD application for testing REST requests. I borrowed quite a bit of code from that application including the plumbing for being able to tie in a D delegate to the GTK thread idle callback so a big thanks to that project for this.
Finally, I’d really recommend having some basic proficiency in another language with full bindings in GTK, either C or Python. The reason for this is that there is very little information out there on using D with GTK but GTK examples in other languages are easily ported to D providing you can work through the code of the example. My C and Python knowledge is pretty sparse but I found I knew enough to get by.
Tool Chain
The tool chain for D is somewhat primitive in comparison to Java but is imminently useable. I do all my development on Linux and so ended up using Mono-D and generally had a pretty positive experience. My only complaints are as follows:
- When trying to run a program, you can an error about failing to create a console. Turns out this is an issue with gnome-terminal as documented here. Unsetting the GNOME_DESKTOP_SESSION_ID variable fixed the problem.
- Code completion seems a bit hit and miss, most of the time it works great but once in a while you hit the’.’ and nothing happens.
Debugging can be done in Mono-D using the GDB plugin and I found this to work quite as well when I was dealing with segmentation faults with my multi-threading code.
For builds I used DUB which is somewhat similar to Maven in the Java world in that it is based on convention not configuration and manages dependencies. I found DUB worked quite well for me and have been pretty happy with it though admittedly my two projects are pretty simple.
Conclusion
Based on my experience so far, I think D and GtkD are a great combination for creating GTK applications in Linux. The learning curve is far shorter then using C and the language itself is much more productive then I say that as a C neophyte so take that with a pinch of salt. Additionally, the safety features of D (GC, RAII, exceptions, etc) make for more reliable software in comparison to C.
Python would also be a very good choice, but coming from a Java background D just felt much more comfortable to me.