Gem #105: Lady Ada Kisses Python — Part 1

The GNAT Components Collection (GNATCOLL) has included, since the beginning, a collection of packages to easily interface your Ada applications with scripting languages. This is the layer used in the GPS IDE to provide extensibility via the GPS shell or Python. The use with the GPS shell is just a toy we initially used to bootstrap the process, and was kept for backward compatibility only. On the other hand, Python is an extensively used object-oriented language that comes with its own run-time library, and can be easily extended in C or Ada.

This Gem will not go into the details of Python itself. There are excellent tutorials on the Internet. Instead, we will focus on the benefits that GNATCOLL provides over a direct interface via pragma Import, and show how to make your application scriptable in Python.

The package providing this support is called GNATCOLL.Scripts. As its name implies, it is meant to be a scripting-language-agnostic API. What this means is that your application will not know anything about Python or its API. Instead, you will export some classes and functions from Ada to GNATCOLL. The latter will then make sure that these functions are available for all the supported languages. Although currently we only support Python and the GPS shell, additional languages could conceivably be added in the future (such as JavaScript, Lisp, or Caml), and your application would automatically be scriptable through these.

GNATCOLL also does most of the memory management on your behalf. Python, for instance, uses reference counting to detect when an object can be freed. Lisp implementations, such as Scheme, generally use a form of garbage collection. But these are details you do not need to know about when you program via GNATCOLL.Scripts. In this package, the Ada types are controlled (and themselves use reference counting, as we detailed in an earlier Gem) and will automatically free memory when no longer used. This is of course less error prone, and will avoid a lot of memory leaks in your application.

In fact, GNATCOLL also provides a few minor extensions to the scripting package if you also program a GUI based on GtkAda. The latter (or rather the underlying gtk+ library) also uses its own reference counting. As a result, things can become really complex when you have an Ada object that's exported to Python, and this object is associated with one of the GUI elements in your application. Finding out when the memory is safe to deallocate requires a lot of care, but GNATCOLL takes care of it all on your behalf!

What are the benefits of interfacing with Python? Python, like a lot of scripting languages, has a rather high-level programming API. In particular, it makes the construction of complex data structures relatively easy, both because it provides an important collection of such data structures that are fully integrated in the language, and also through its introspection and reflection capabilities. Our experience from GPS is that a lot of users (provided they are programmers, of course) will readily be able to understand Python script, and by using simple copy-paste will be able to quickly write their own scripts.

For GPS there are a number of user groups that have developed extensive Python modules to change the behavior of GPS and better integrate it in their own environment. Had we chosen to use Ada as the language for such extensions, it would have required users to have the full GPS development environment in order to build them, relink GPS (or create dynamically loaded libraries), and finally to test their changes. By comparison, the Python cycle is much faster: just edit and reload. Supportwise, it is also often convenient for us to provide a quick and short Python script to work around a GPS limitation and unblock customers, until we have time to do the proper work at the Ada level. Finally, there are features that are required by one customer, but which would make no sense for others; in such a case, the easiest thing to do is to implement it via a short Python script in coordination with the customer. If the Python API is kept stable, the script will continue to work from version to version of GPS.

In the second part of this Gem series, we'll show specific technical details of how to interface an application with Python using GNATCOLL.