The steps described so far implement an initial Guile integration that already gives a lot of additional power to Dia application users. But there are further steps that you could take, and it’s interesting to consider a few of these.
In general, you could progressively move more of Dia’s source code from C into Scheme. This might make the code more maintainable and extensible, and it could open the door to new programming paradigms that are tricky to effect in C but straightforward in Scheme.
A specific example of this is that you could use the guile-gtk package, which provides Scheme-level procedures for most of the Gtk+ library, to move the code that lays out and displays Dia objects from C to Scheme.
As you follow this path, it naturally becomes less useful to maintain a distinction between Dia’s original non-Guile-related source code, and its later code implementing foreign objects and primitives for the Scheme world.
For example, suppose that the original source code had a
dia_change_fill_pattern
function:
void dia_change_fill_pattern (struct dia_shape * shape, struct dia_pattern * pattern) { /* real pattern change work */ }
During initial Guile integration, you add a change_fill_pattern
primitive for Scheme purposes, which accesses the underlying structures
from its foreign object values and uses dia_change_fill_pattern
to do the real work:
SCM change_fill_pattern (SCM shape, SCM pattern) { struct dia_shape * d_shape; struct dia_pattern * d_pattern; ... dia_change_fill_pattern (d_shape, d_pattern); return SCM_UNSPECIFIED; }
At this point, it makes sense to keep dia_change_fill_pattern
and
change_fill_pattern
separate, because
dia_change_fill_pattern
can also be called without going through
Scheme at all, say because the user clicks a button which causes a
C-registered Gtk+ callback to be called.
But, if the code for creating buttons and registering their callbacks is
moved into Scheme (using guile-gtk), it may become true that
dia_change_fill_pattern
can no longer be called other than
through Scheme. In which case, it makes sense to abolish it and move
its contents directly into change_fill_pattern
, like this:
SCM change_fill_pattern (SCM shape, SCM pattern) { struct dia_shape * d_shape; struct dia_pattern * d_pattern; ... /* real pattern change work */ return SCM_UNSPECIFIED; }
So further Guile integration progressively reduces the amount of functional C code that you have to maintain over the long term.
A similar argument applies to data representation. In the discussion of foreign objects earlier, issues arose because of the different memory management and lifetime models that normally apply to data structures in C and in Scheme. However, with further Guile integration, you can resolve this issue in a more radical way by allowing all your data structures to be under the control of the garbage collector, and kept alive by references from the Scheme world. Instead of maintaining an array or linked list of shapes in C, you would instead maintain a list in Scheme.
Rather like the coalescing of dia_change_fill_pattern
and
change_fill_pattern
, the practical upshot of such a change is
that you would no longer have to keep the dia_shape
and
dia_guile_shape
structures separate, and so wouldn’t need to
worry about the pointers between them. Instead, you could change the
foreign object definition to wrap the dia_shape
structure
directly, and send dia_guile_shape
off to the scrap yard. Cut
out the middle man!
Finally, we come to the holy grail of Guile’s free software / extension language approach. Once you have a Scheme representation for interesting Dia data types like shapes, and a handy bunch of primitives for manipulating them, it suddenly becomes clear that you have a bundle of functionality that could have far-ranging use beyond Dia itself. In other words, the data types and primitives could now become a library, and Dia becomes just one of the many possible applications using that library — albeit, at this early stage, a rather important one!
In this model, Guile becomes just the glue that binds everything together. Imagine an application that usefully combined functionality from Dia, Gnumeric and GnuCash — it’s tricky right now, because no such application yet exists; but it’ll happen some day …