Commit | Line | Data |
---|---|---|
9401323e | 1 | @page |
226297eb NJ |
2 | @node Programming Overview |
3 | @chapter An Overview of Guile Programming | |
4 | ||
5 | Guile is designed as an extension language interpreter that is | |
6 | straightforward to integrate with applications written in C (and C++). | |
7 | The big win here for the application developer is that Guile | |
8 | integration, as the Guile web page says, ``lowers your project's | |
9 | hacktivation energy.'' Lowering the hacktivation energy means that you, | |
10 | as the application developer, @emph{and your users}, reap the benefits | |
11 | that flow from being able to extend the application in a high level | |
12 | extension language rather than in plain old C. | |
13 | ||
1982a56a NJ |
14 | In abstract terms, it's difficult to explain what this really means and |
15 | what the integration process involves, so instead let's begin by jumping | |
16 | straight into an example of how you might integrate Guile into an | |
17 | existing program, and what you could expect to gain by so doing. With | |
18 | that example under our belts, we'll then return to a more general | |
19 | analysis of the arguments involved and the range of programming options | |
20 | available. | |
21 | ||
22 | @menu | |
23 | * Extending Dia:: How one might extend Dia using Guile. | |
24 | * Scheme vs C:: Why Scheme is more hackable than C. | |
25 | * Testbed Example:: Example: using Guile in a testbed. | |
26 | * Programming Options:: Options for Guile programming. | |
27 | * User Programming:: How about application users? | |
28 | @end menu | |
29 | ||
30 | ||
31 | @node Extending Dia | |
32 | @section How One Might Extend Dia Using Guile | |
33 | ||
34 | Dia is a free software program for drawing schematic diagrams like flow | |
35 | charts and floor plans (REFFIXME). This section conducts the thought | |
36 | experiment of adding Guile to Dia. In so doing, it aims to illustrate | |
37 | several of the steps and considerations involved in adding Guile to | |
38 | applications in general. | |
39 | ||
40 | @menu | |
41 | * Dia Objective:: Deciding why you want to add Guile. | |
42 | * Dia Steps:: Four steps required to add Guile. | |
43 | * Dia Smobs:: How to represent Dia data in Scheme. | |
44 | * Dia Primitives:: Writing Guile primitives for Dia. | |
45 | * Dia Hook:: Providing a hook for Scheme evaluation. | |
46 | * Dia Structure:: Overall structure for adding Guile. | |
47 | * Dia Advanced:: Going further with Dia and Guile. | |
48 | @end menu | |
49 | ||
50 | ||
51 | @node Dia Objective | |
52 | @subsection Deciding Why You Want to Add Guile | |
53 | ||
54 | First off, you should understand why you want to add Guile to Dia at | |
55 | all, and that means forming a picture of what Dia does and how it does | |
56 | it. So, what are the constituents of the Dia application? | |
57 | ||
58 | @itemize @bullet | |
59 | @item | |
60 | Most importantly, the @dfn{application domain objects} --- in other | |
61 | words, the concepts that differentiate Dia from another application such | |
62 | as a word processor or spreadsheet: shapes, templates, connectors, | |
63 | pages, plus the properties of all these things. | |
64 | ||
65 | @item | |
66 | The code that manages the graphical face of the application, including | |
67 | the layout and display of the objects above. | |
68 | ||
69 | @item | |
70 | The code that handles input events, which indicate that the application | |
71 | user is wanting to do something. | |
72 | @end itemize | |
73 | ||
74 | @noindent | |
75 | (In other words, a textbook example of the @dfn{model - view - | |
76 | controller} paradigm.) | |
77 | ||
78 | Next question: how will Dia benefit once the Guile integration is | |
79 | complete? Several (positive!) answers are possible here, and the choice | |
80 | is obviously up to the application developers. Still, one answer is | |
81 | that the main benefit will be the ability to manipulate Dia's | |
82 | application domain objects from Scheme. | |
83 | ||
84 | Suppose that Dia made a set of procedures available in Scheme, | |
85 | representing the most basic operations on objects such as shapes, | |
86 | connectors, and so on. Using Scheme, the application user could then | |
87 | write code that builds upon these basic operations to create more | |
88 | complex procedures. For example, given basic procedures to enumerate | |
89 | the objects on a page, to determine whether an object is a square, and | |
90 | to change the fill pattern of a single shape, the user can write a | |
91 | Scheme procedure to change the fill pattern of all squares on the | |
92 | current page: | |
93 | ||
94 | @lisp | |
95 | (define (change-squares'-fill-pattern new-pattern) | |
96 | (for-each-shape current-page | |
97 | (lambda (shape) | |
98 | (if (square? shape) | |
99 | (change-fill-pattern shape new-pattern))))) | |
100 | @end lisp | |
101 | ||
102 | ||
103 | @node Dia Steps | |
104 | @subsection Four Steps Required to Add Guile | |
105 | ||
106 | Assuming this objective, four steps are needed to achieve it. | |
107 | ||
108 | First, you need a way of representing your application-specific objects | |
109 | --- such as @code{shape} in the previous example --- when they are | |
110 | passed into the Scheme world. Unless your objects are so simple that | |
111 | they map naturally into builtin Scheme data types like numbers and | |
112 | strings, you will probably want to use Guile's @dfn{SMOB} interface to | |
113 | create a new Scheme data type for your objects. | |
114 | ||
115 | Second, you need to write code for the basic operations like | |
116 | @code{for-each-shape} and @code{square?} such that they access and | |
117 | manipulate your existing data structures correctly, and then make these | |
118 | operations available as @dfn{primitives} on the Scheme level. | |
119 | ||
120 | Third, you need to provide some mechanism within the Dia application | |
121 | that a user can hook into to cause arbitrary Scheme code to be | |
122 | evaluated. | |
123 | ||
124 | Finally, you need to restructure your top-level application C code a | |
125 | little so that it initializes the Guile interpreter correctly and | |
126 | declares your @dfn{SMOBs} and @dfn{primitives} to the Scheme world. | |
127 | ||
128 | The following subsections expand on these four points in turn. | |
129 | ||
130 | ||
131 | @node Dia Smobs | |
132 | @subsection How to Represent Dia Data in Scheme | |
133 | ||
134 | For all but the most trivial applications, you will probably want to | |
135 | allow some representation of your domain objects to exist on the Scheme | |
136 | level. This is where the idea of SMOBs comes in, and with it issues of | |
137 | lifetime management and garbage collection. | |
138 | ||
139 | To get more concrete about this, let's look again at the example we gave | |
140 | earlier of how application users can use Guile to build higher-level | |
141 | functions from the primitives that Dia itself provides. | |
142 | ||
143 | @lisp | |
144 | (define (change-squares'-fill-pattern new-pattern) | |
145 | (for-each-shape current-page | |
146 | (lambda (shape) | |
147 | (if (square? shape) | |
148 | (change-fill-pattern shape new-pattern))))) | |
149 | @end lisp | |
150 | ||
151 | Consider what is stored here in the variable @code{shape}. For each | |
152 | shape on the current page, the @code{for-each-shape} primitive calls | |
153 | @code{(lambda (shape) @dots{})} with an argument representing that | |
154 | shape. Question is: how is that argument represented on the Scheme | |
155 | level? The issues are as follows. | |
156 | ||
157 | @itemize @bullet | |
158 | @item | |
159 | Whatever the representation, it has to be decodable again by the C code | |
160 | for the @code{square?} and @code{change-fill-pattern} primitives. In | |
161 | other words, a primitive like @code{square?} has somehow to be able to | |
162 | turn the value that it receives back into something that points to the | |
163 | underlying C structure describing a shape. | |
164 | ||
165 | @item | |
166 | The representation must also cope with Scheme code holding on to the | |
167 | value for later use. What happens if the Scheme code stores | |
168 | @code{shape} in a global variable, but then that shape is deleted (in a | |
169 | way that the Scheme code is not aware of), and later on some other | |
170 | Scheme code uses that global variable again in a call to, say, | |
171 | @code{square?}? | |
172 | ||
173 | @item | |
174 | The lifetime and memory allocation of objects that exist @emph{only} in | |
175 | the Scheme world is managed automatically by Guile's garbage collector | |
176 | using one simple rule: when there are no remaining references to an | |
177 | object, the object is considered dead and so its memory is freed. But | |
178 | for objects that exist in both C and Scheme, the picture is more | |
179 | complicated; in the case of Dia, where the @code{shape} argument passes | |
180 | transiently in and out of the Scheme world, it would be quite wrong the | |
181 | @strong{delete} the underlying C shape just because the Scheme code has | |
182 | finished evaluation. How do we avoid this happening? | |
183 | @end itemize | |
184 | ||
185 | One resolution of these issues is for the Scheme-level representation of | |
186 | a shape to be a new, Scheme-specific C structure wrapped up as a SMOB. | |
187 | The SMOB is what is passed into and out of Scheme code, and the | |
188 | Scheme-specific C structure inside the SMOB points to Dia's underlying C | |
189 | structure so that the code for primitives like @code{square?} can get at | |
190 | it. | |
191 | ||
192 | To cope with an underlying shape being deleted while Scheme code is | |
193 | still holding onto a Scheme shape value, the underlying C structure | |
194 | should have a new field that points to the Scheme-specific SMOB. When a | |
195 | shape is deleted, the relevant code chains through to the | |
196 | Scheme-specific structure and sets its pointer back to the underlying | |
197 | structure to NULL. Thus the SMOB value for the shape continues to | |
198 | exist, but any primitive code that tries to use it will detect that the | |
199 | underlying shape has been deleted because the underlying structure | |
200 | pointer is NULL. | |
201 | ||
202 | So, to summarize the steps involved in this resolution of the problem | |
203 | (and assuming that the underlying C structure for a shape is | |
204 | @code{struct dia_shape}): | |
205 | ||
206 | @itemize @bullet | |
207 | @item | |
208 | Define a new Scheme-specific structure that @emph{points} to the | |
209 | underlying C structure: | |
210 | ||
211 | @lisp | |
212 | struct dia_guile_shape | |
213 | @{ | |
214 | struct dia_shape * c_shape; /* NULL => deleted */ | |
215 | @} | |
216 | @end lisp | |
217 | ||
218 | @item | |
219 | Add a field to @code{struct dia_shape} that points to its @code{struct | |
220 | dia_guile_shape} if it has one --- | |
221 | ||
222 | @lisp | |
223 | struct dia_shape | |
224 | @{ | |
225 | @dots{} | |
226 | struct dia_guile_shape * guile_shape; | |
227 | @} | |
228 | @end lisp | |
229 | ||
230 | @noindent | |
231 | --- so that C code can set @code{guile_shape->c_shape} to NULL when the | |
232 | underlying shape is deleted. | |
233 | ||
234 | @item | |
235 | Wrap @code{struct dia_guile_shape} as a SMOB type. | |
236 | ||
237 | @item | |
238 | Whenever you need to represent a C shape onto the Scheme level, create a | |
239 | SMOB instance for it, and pass that. | |
240 | ||
241 | @item | |
242 | In primitive code that receives a shape SMOB instance, check the | |
243 | @code{c_shape} field when decoding it, to find out whether the | |
244 | underlying C shape is still there. | |
245 | @end itemize | |
246 | ||
247 | As far as memory management is concerned, the SMOB values and their | |
248 | Scheme-specific structures are under the control of the garbage | |
249 | collector, whereas the underlying C structures are explicitly managed in | |
250 | exactly the same way that Dia managed them before we thought of adding | |
251 | Guile. | |
252 | ||
253 | When the garbage collector decides to free a shape SMOB value, it calls | |
254 | the @dfn{SMOB free} function that was specified when defining the shape | |
255 | SMOB type. To maintain the correctness of the @code{guile_shape} field | |
256 | in the underlying C structure, this function should chain through to the | |
257 | underlying C structure (if it still exists) and set its | |
258 | @code{guile_shape} field to NULL. | |
259 | ||
260 | For full documentation on defining and using SMOB types, see | |
261 | @ref{Defining New Types (Smobs)}. | |
262 | ||
263 | ||
264 | @node Dia Primitives | |
265 | @subsection Writing Guile Primitives for Dia | |
266 | ||
267 | Once the details of object representation are decided, writing the | |
268 | primitive function code that you need is usually straightforward. | |
269 | ||
270 | A primitive is simply a C function whose arguments and return value are | |
271 | all of type @code{SCM}, and whose body does whatever you want it to do. | |
272 | As an example, here is a possible implementation of the @code{square?} | |
273 | primitive: | |
274 | ||
275 | @lisp | |
276 | #define FUNC_NAME "square?" | |
277 | static SCM square_p (SCM shape) | |
278 | @{ | |
279 | struct dia_guile_shape * guile_shape; | |
280 | ||
281 | /* Check that arg is really a shape SMOB. */ | |
282 | SCM_VALIDATE_SHAPE (SCM_ARG1, shape); | |
283 | ||
284 | /* Access Scheme-specific shape structure. */ | |
285 | guile_shape = SCM_SMOB_DATA (shape); | |
286 | ||
287 | /* Find out if underlying shape exists and is a | |
288 | square; return answer as a Scheme boolean. */ | |
289 | return SCM_BOOL (guile_shape->c_shape && | |
290 | (guile_shape->c_shape->type == DIA_SQUARE)); | |
291 | @} | |
292 | #undef FUNC_NAME | |
293 | @end lisp | |
294 | ||
295 | Notice how easy it is to chain through from the @code{SCM shape} | |
296 | parameter that @code{square_p} receives --- which is a SMOB --- to the | |
297 | Scheme-specific structure inside the SMOB, and thence to the underlying | |
298 | C structure for the shape. | |
299 | ||
300 | In this code, @code{SCM_SMOB_DATA} and @code{SCM_BOOL} are macros from | |
301 | the standard Guile API. @code{SCM_VALIDATE_SHAPE} is a macro that you | |
302 | should define as part of your SMOB definition: it checks that the passed | |
303 | parameter is of the expected type. This is needed to guard against | |
304 | Scheme code using the @code{square?} procedure incorrectly, as in | |
305 | @code{(square? "hello")}; Scheme's latent typing means that usage errors | |
306 | like this must be caught at run time. | |
307 | ||
308 | Having written the C code for your primitives, you need to make them | |
309 | available as Scheme procedures by calling the @code{scm_c_define_gsubr} | |
310 | function. @code{scm_c_define_gsubr} (REFFIXME) takes arguments that | |
311 | specify the Scheme-level name for the primitive and how many required, | |
312 | optional and rest arguments it can accept. The @code{square?} primitive | |
313 | always requires exactly one argument, so the call to make it available | |
314 | in Scheme reads like this: | |
315 | ||
316 | @lisp | |
317 | scm_c_define_gsubr ("square?", 1, 0, 0, square_p); | |
318 | @end lisp | |
319 | ||
320 | For where to put this call, see the subsection after next on the | |
321 | structure of Guile-enabled code (@pxref{Dia Structure}). | |
322 | ||
323 | ||
324 | @node Dia Hook | |
325 | @subsection Providing a Hook for the Evaluation of Scheme Code | |
326 | ||
327 | To make the Guile integration useful, you have to design some kind of | |
328 | hook into your application that application users can use to cause their | |
329 | Scheme code to be evaluated. | |
330 | ||
331 | Technically, this is straightforward; you just have to decide on a | |
332 | mechanism that is appropriate for your application. Think of Emacs, for | |
333 | example: when you type @kbd{@key{ESC} :}, you get a prompt where you can | |
334 | type in any Elisp code, which Emacs will then evaluate. Or, again like | |
335 | Emacs, you could provide a mechanism (such as an init file) to allow | |
336 | Scheme code to be associated with a particular key sequence, and | |
337 | evaluate the code when that key sequence is entered. | |
338 | ||
339 | In either case, once you have the Scheme code that you want to evaluate, | |
340 | as a null terminated string, you can tell Guile to evaluate it by | |
341 | calling the @code{scm_c_eval_string} function. | |
342 | ||
343 | ||
344 | @node Dia Structure | |
345 | @subsection Top-level Structure of Guile-enabled Dia | |
346 | ||
347 | Let's assume that the pre-Guile Dia code looks structurally like this: | |
348 | ||
349 | @itemize @bullet | |
350 | @item | |
351 | @code{main ()} | |
352 | ||
353 | @itemize @bullet | |
354 | @item | |
355 | do lots of initialization and setup stuff | |
356 | @item | |
357 | enter Gtk main loop | |
358 | @end itemize | |
359 | @end itemize | |
360 | ||
361 | When you add Guile to a program, one (rather technical) requirement is | |
362 | that Guile's garbage collector needs to know where the bottom of the C | |
363 | stack is. The easiest way to ensure this is to use | |
364 | @code{scm_boot_guile} like this: | |
365 | ||
366 | @itemize @bullet | |
367 | @item | |
368 | @code{main ()} | |
369 | ||
370 | @itemize @bullet | |
371 | @item | |
372 | do lots of initialization and setup stuff | |
373 | @item | |
374 | @code{scm_boot_guile (argc, argv, inner_main, NULL)} | |
375 | @end itemize | |
376 | ||
377 | @item | |
378 | @code{inner_main ()} | |
379 | ||
380 | @itemize @bullet | |
381 | @item | |
382 | define all SMOB types | |
383 | @item | |
384 | export primitives to Scheme using @code{scm_c_define_gsubr} | |
385 | @item | |
386 | enter Gtk main loop | |
387 | @end itemize | |
388 | @end itemize | |
389 | ||
390 | In other words, you move the guts of what was previously in your | |
391 | @code{main} function into a new function called @code{inner_main}, and | |
392 | then add a @code{scm_boot_guile} call, with @code{inner_main} as a | |
393 | parameter, to the end of @code{main}. | |
394 | ||
395 | Assuming that you are using SMOBs and have written primitive code as | |
396 | described in the preceding subsections, you also need to insert calls to | |
397 | declare your new SMOBs and export the primitives to Scheme. These | |
398 | declarations must happen @emph{inside} the dynamic scope of the | |
399 | @code{scm_boot_guile} call, but also @emph{before} any code is run that | |
400 | could possibly use them --- the beginning of @code{inner_main} is an | |
401 | ideal place for this. | |
402 | ||
403 | ||
404 | @node Dia Advanced | |
405 | @subsection Going Further with Dia and Guile | |
406 | ||
407 | The steps described so far implement an initial Guile integration that | |
408 | already gives a lot of additional power to Dia application users. But | |
409 | there are further steps that you could take, and it's interesting to | |
410 | consider a few of these. | |
411 | ||
412 | In general, you could progressively move more of Dia's source code from | |
413 | C into Scheme. This might make the code more maintainable and | |
414 | extensible, and it could open the door to new programming paradigms that | |
415 | are tricky to effect in C but straightforward in Scheme. | |
416 | ||
417 | A specific example of this is that you could use the guile-gtk package, | |
418 | which provides Scheme-level procedures for most of the Gtk+ library, to | |
419 | move the code that lays out and displays Dia objects from C to Scheme. | |
420 | ||
421 | As you follow this path, it naturally becomes less useful to maintain a | |
422 | distinction between Dia's original non-Guile-related source code, and | |
423 | its later code implementing SMOBs and primitives for the Scheme world. | |
424 | ||
425 | For example, suppose that the original source code had a | |
426 | @code{dia_change_fill_pattern} function: | |
427 | ||
428 | @lisp | |
429 | void dia_change_fill_pattern (struct dia_shape * shape, | |
430 | struct dia_pattern * pattern) | |
431 | @{ | |
432 | /* real pattern change work */ | |
433 | @} | |
434 | @end lisp | |
435 | ||
436 | During initial Guile integration, you add a @code{change_fill_pattern} | |
437 | primitive for Scheme purposes, which accesses the underlying structures | |
438 | from its SMOB values and uses @code{dia_change_fill_pattern} to do the | |
439 | real work: | |
440 | ||
441 | @lisp | |
442 | SCM change_fill_pattern (SCM shape, SCM pattern) | |
443 | @{ | |
444 | struct dia_shape * d_shape; | |
445 | struct dia_pattern * d_pattern; | |
446 | ||
447 | @dots{} | |
448 | ||
449 | dia_change_fill_pattern (d_shape, d_pattern); | |
450 | ||
451 | return SCM_UNSPECIFIED; | |
452 | @} | |
453 | @end lisp | |
454 | ||
455 | At this point, it makes sense to keep @code{dia_change_fill_pattern} and | |
456 | @code{change_fill_pattern} separate, because | |
457 | @code{dia_change_fill_pattern} can also be called without going through | |
458 | Scheme at all, say because the user clicks a button which causes a | |
459 | C-registered Gtk+ callback to be called. | |
460 | ||
461 | But, if the code for creating buttons and registering their callbacks is | |
462 | moved into Scheme (using guile-gtk), it may become true that | |
463 | @code{dia_change_fill_pattern} can no longer be called other than | |
464 | through Scheme. In which case, it makes sense to abolish it and move | |
465 | its contents directly into @code{change_fill_pattern}, like this: | |
466 | ||
467 | @lisp | |
468 | SCM change_fill_pattern (SCM shape, SCM pattern) | |
469 | @{ | |
470 | struct dia_shape * d_shape; | |
471 | struct dia_pattern * d_pattern; | |
472 | ||
473 | @dots{} | |
474 | ||
475 | /* real pattern change work */ | |
476 | ||
477 | return SCM_UNSPECIFIED; | |
478 | @} | |
479 | @end lisp | |
480 | ||
481 | So further Guile integration progressively @emph{reduces} the amount of | |
482 | functional C code that you have to maintain over the long term. | |
483 | ||
484 | A similar argument applies to data representation. In the discussion of | |
485 | SMOBs earlier, issues arose because of the different memory management | |
486 | and lifetime models that normally apply to data structures in C and in | |
487 | Scheme. However, with further Guile integration, you can resolve this | |
488 | issue in a more radical way by allowing all your data structures to be | |
489 | under the control of the garbage collector, and kept alive by references | |
490 | from the Scheme world. Instead of maintaining an array or linked list | |
491 | of shapes in C, you would instead maintain a list in Scheme. | |
492 | ||
493 | Rather like the coalescing of @code{dia_change_fill_pattern} and | |
494 | @code{change_fill_pattern}, the practical upshot of such a change is | |
495 | that you would no longer have to keep the @code{dia_shape} and | |
496 | @code{dia_guile_shape} structures separate, and so wouldn't need to | |
497 | worry about the pointers between them. Instead, you could change the | |
498 | SMOB definition to wrap the @code{dia_shape} structure directly, and | |
499 | send @code{dia_guile_shape} off to the scrap yard. Cut out the middle | |
500 | man! | |
501 | ||
502 | Finally, we come to the holy grail of Guile's free software / extension | |
503 | language approach. Once you have a Scheme representation for | |
504 | interesting Dia data types like shapes, and a handy bunch of primitives | |
505 | for manipulating them, it suddenly becomes clear that you have a bundle | |
506 | of functionality that could have far-ranging use beyond Dia itself. In | |
507 | other words, the data types and primitives could now become a library, | |
508 | and Dia becomes just one of the many possible applications using that | |
509 | library --- albeit, at this early stage, a rather important one! | |
510 | ||
511 | In this model, Guile becomes just the glue that binds everything | |
512 | together. Imagine an application that usefully combined functionality | |
513 | from Dia, Gnumeric and GnuCash --- it's tricky right now, because no | |
514 | such application yet exists; but it'll happen some day @dots{} | |
515 | ||
516 | ||
517 | @node Scheme vs C | |
518 | @section Why Scheme is More Hackable Than C | |
519 | ||
520 | Underlying Guile's value proposition is the assumption that programming | |
521 | in a high level language, specifically Guile's implementation of Scheme, | |
522 | is necessarily better in some way than programming in C. What do we | |
523 | mean by this claim, and how can we be so sure? | |
226297eb NJ |
524 | |
525 | One class of advantages applies not only to Scheme, but more generally | |
526 | to any interpretable, high level, scripting language, such as Emacs | |
527 | Lisp, Python, Ruby, or @TeX{}'s macro language. Common features of all | |
528 | such languages, when compared to C, are that: | |
9401323e NJ |
529 | |
530 | @itemize @bullet | |
531 | @item | |
226297eb NJ |
532 | They lend themselves to rapid and experimental development cycles, |
533 | owing usually to a combination of their interpretability and the | |
534 | integrated development environment in which they are used. | |
9401323e NJ |
535 | |
536 | @item | |
226297eb NJ |
537 | They free developers from some of the low level bookkeeping tasks |
538 | associated with C programming, notably memory management. | |
9401323e NJ |
539 | |
540 | @item | |
226297eb NJ |
541 | They provide high level features such as container objects and exception |
542 | handling that make common programming tasks easier. | |
9401323e NJ |
543 | @end itemize |
544 | ||
1982a56a NJ |
545 | In the case of Scheme, particular features that make programming easier |
546 | --- and more fun! --- are its powerful mechanisms for abstracting parts | |
547 | of programs (closures --- @pxref{About Closure}) and for iteration | |
226297eb NJ |
548 | (@pxref{while do}). |
549 | ||
550 | The evidence in support of this argument is empirical: the huge amount | |
551 | of code that has been written in extension languages for applications | |
552 | that support this mechanism. Most notable are extensions written in | |
553 | Emacs Lisp for GNU Emacs, in @TeX{}'s macro language for @TeX{}, and in | |
554 | Script-Fu for the Gimp, but there is increasingly now a significant code | |
555 | eco-system for Guile-based applications as well, such as Lilypond and | |
556 | GnuCash. It is close to inconceivable that similar amounts of | |
557 | functionality could have been added to these applications just by | |
558 | writing new code in their base implementation languages. | |
559 | ||
226297eb NJ |
560 | |
561 | @node Testbed Example | |
562 | @section Example: Using Guile for an Application Testbed | |
563 | ||
564 | As an example of what this means in practice, imagine writing a testbed | |
565 | for an application that is tested by submitting various requests (via a | |
566 | C interface) and validating the output received. Suppose further that | |
567 | the application keeps an idea of its current state, and that the | |
568 | ``correct'' output for a given request may depend on the current | |
569 | application state. A complete ``white box''@footnote{A @dfn{white box} | |
570 | test plan is one that incorporates knowledge of the internal design of | |
571 | the application under test.} test plan for this application would aim to | |
572 | submit all possible requests in each distinguishable state, and validate | |
573 | the output for all request/state combinations. | |
574 | ||
575 | To write all this test code in C would be very tedious. Suppose instead | |
576 | that the testbed code adds a single new C function, to submit an | |
577 | arbitrary request and return the response, and then uses Guile to export | |
578 | this function as a Scheme procedure. The rest of the testbed can then | |
579 | be written in Scheme, and so benefits from all the advantages of | |
580 | programming in Scheme that were described in the previous section. | |
581 | ||
582 | (In this particular example, there is an additional benefit of writing | |
583 | most of the testbed in Scheme. A common problem for white box testing | |
584 | is that mistakes and mistaken assumptions in the application under test | |
585 | can easily be reproduced in the testbed code. It is more difficult to | |
586 | copy mistakes like this when the testbed is written in a different | |
587 | language from the application.) | |
588 | ||
589 | ||
590 | @node Programming Options | |
591 | @section A Choice of Programming Options | |
592 | ||
593 | The preceding arguments and example point to a model of Guile | |
594 | programming that is applicable in many cases. According to this model, | |
595 | Guile programming involves a balance between C and Scheme programming, | |
596 | with the aim being to extract the greatest possible Scheme level benefit | |
597 | from the least amount of C level work. | |
598 | ||
599 | The C level work required in this model usually consists of packaging | |
600 | and exporting functions and application objects such that they can be | |
601 | seen and manipulated on the Scheme level. To help with this, Guile's C | |
602 | language interface includes utility features that aim to make this kind | |
603 | of integration very easy for the application developer. These features | |
604 | are documented later in this part of the manual: see REFFIXME. | |
605 | ||
606 | This model, though, is really just one of a range of possible | |
607 | programming options. If all of the functionality that you need is | |
608 | available from Scheme, you could choose instead to write your whole | |
609 | application in Scheme (or one of the other high level languages that | |
610 | Guile supports through translation), and simply use Guile as an | |
611 | interpreter for Scheme. (In the future, we hope that Guile will also be | |
612 | able to compile Scheme code, so lessening the performance gap between C | |
613 | and Scheme code.) Or, at the other end of the C--Scheme scale, you | |
614 | could write the majority of your application in C, and only call out to | |
615 | Guile occasionally for specific actions such as reading a configuration | |
616 | file or executing a user-specified extension. The choices boil down to | |
617 | two basic questions: | |
9401323e NJ |
618 | |
619 | @itemize @bullet | |
620 | @item | |
621 | Which parts of the application do you write in C, and which in Scheme | |
622 | (or another high level translated language)? | |
623 | ||
624 | @item | |
625 | How do you design the interface between the C and Scheme parts of your | |
626 | application? | |
627 | @end itemize | |
628 | ||
629 | These are of course design questions, and the right design for any given | |
630 | application will always depend upon the particular requirements that you | |
226297eb NJ |
631 | are trying to meet. In the context of Guile, however, there are some |
632 | generally applicable considerations that can help you when designing | |
633 | your answers. | |
9401323e NJ |
634 | |
635 | @menu | |
636 | * Available Functionality:: What functionality is already available? | |
637 | * Basic Constraints:: Functional and performance constraints. | |
638 | * Style Choices:: Your preferred programming style. | |
639 | * Program Control:: What controls program execution? | |
9401323e NJ |
640 | @end menu |
641 | ||
642 | ||
643 | @node Available Functionality | |
226297eb | 644 | @subsection What Functionality is Already Available? |
9401323e NJ |
645 | |
646 | Suppose, for the sake of argument, that you would prefer to write your | |
647 | whole application in Scheme. Then the API available to you consists of: | |
648 | ||
649 | @itemize @bullet | |
650 | @item | |
651 | standard Scheme | |
652 | ||
653 | @item | |
654 | plus the extensions to standard Scheme provided by | |
655 | Guile in its core distribution | |
656 | ||
657 | @item | |
658 | plus any additional functionality that you or others have packaged so | |
659 | that it can be loaded as a Guile Scheme module. | |
660 | @end itemize | |
661 | ||
662 | A module in the last category can either be a pure Scheme module --- in | |
663 | other words a collection of utility procedures coded in Scheme --- or a | |
664 | module that provides a Scheme interface to an extension library coded in | |
665 | C --- in other words a nice package where someone else has done the work | |
666 | of wrapping up some useful C code for you. The set of available modules | |
667 | is growing quickly and already includes such useful examples as | |
668 | @code{(gtk gtk)}, which makes Gtk+ drawing functions available in | |
669 | Scheme, and @code{(database postgres)}, which provides SQL access to a | |
670 | Postgres database. | |
671 | ||
a7a7bb95 NJ |
672 | Given the growing collection of pre-existing modules, it is quite |
673 | feasible that your application could be implemented by combining a | |
674 | selection of these modules together with new application code written in | |
675 | Scheme. | |
676 | ||
677 | If this approach is not enough, because the functionality that your | |
226297eb NJ |
678 | application needs is not already available in this form, and it is |
679 | impossible to write the new functionality in Scheme, you will need to | |
680 | write some C code. If the required function is already available in C | |
681 | (e.g. in a library), all you need is a little glue to connect it to the | |
682 | world of Guile. If not, you need both to write the basic code and to | |
683 | plumb it into Guile. | |
9401323e NJ |
684 | |
685 | In either case, two general considerations are important. Firstly, what | |
686 | is the interface by which the functionality is presented to the Scheme | |
687 | world? Does the interface consist only of function calls (for example, | |
688 | a simple drawing interface), or does it need to include @dfn{objects} of | |
689 | some kind that can be passed between C and Scheme and manipulated by | |
690 | both worlds. Secondly, how does the lifetime and memory management of | |
691 | objects in the C code relate to the garbage collection governed approach | |
692 | of Scheme objects? In the case where the basic C code is not already | |
693 | written, most of the difficulties of memory management can be avoided by | |
694 | using Guile's C interface features from the start. | |
695 | ||
226297eb NJ |
696 | For the full documentation on writing C code for Guile and connecting |
697 | existing C code to the Guile world, see REFFIXME. | |
9401323e NJ |
698 | |
699 | ||
700 | @node Basic Constraints | |
226297eb | 701 | @subsection Functional and Performance Constraints |
9401323e NJ |
702 | |
703 | ||
704 | @node Style Choices | |
226297eb | 705 | @subsection Your Preferred Programming Style |
9401323e NJ |
706 | |
707 | ||
708 | @node Program Control | |
226297eb | 709 | @subsection What Controls Program Execution? |
9401323e | 710 | |
9401323e NJ |
711 | |
712 | @node User Programming | |
713 | @section How About Application Users? | |
714 | ||
715 | So far we have considered what Guile programming means for an | |
716 | application developer. But what if you are instead @emph{using} an | |
717 | existing Guile-based application, and want to know what your | |
718 | options are for programming and extending this application? | |
719 | ||
720 | The answer to this question varies from one application to another, | |
721 | because the options available depend inevitably on whether the | |
722 | application developer has provided any hooks for you to hang your own | |
723 | code on and, if there are such hooks, what they allow you to | |
724 | do.@footnote{Of course, in the world of free software, you always have | |
725 | the freedom to modify the application's source code to your own | |
726 | requirements. Here we are concerned with the extension options that the | |
727 | application has provided for without your needing to modify its source | |
728 | code.} For example@dots{} | |
729 | ||
730 | @itemize @bullet | |
731 | @item | |
732 | If the application permits you to load and execute any Guile code, the | |
733 | world is your oyster. You can extend the application in any way that | |
734 | you choose. | |
735 | ||
736 | @item | |
737 | A more cautious application might allow you to load and execute Guile | |
738 | code, but only in a @dfn{safe} environment, where the interface | |
739 | available is restricted by the application from the standard Guile API. | |
740 | ||
741 | @item | |
742 | Or a really fearful application might not provide a hook to really | |
743 | execute user code at all, but just use Scheme syntax as a convenient way | |
744 | for users to specify application data or configuration options. | |
745 | @end itemize | |
746 | ||
747 | In the last two cases, what you can do is, by definition, restricted by | |
748 | the application, and you should refer to the application's own manual to | |
749 | find out your options. | |
750 | ||
751 | The most well known example of the first case is Emacs, with its | |
752 | extension language Emacs Lisp: as well as being a text editor, Emacs | |
753 | supports the loading and execution of arbitrary Emacs Lisp code. The | |
754 | result of such openness has been dramatic: Emacs now benefits from | |
755 | user-contributed Emacs Lisp libraries that extend the basic editing | |
756 | function to do everything from reading news to psychoanalysis and | |
757 | playing adventure games. The only limitation is that extensions are | |
758 | restricted to the functionality provided by Emacs's built-in set of | |
759 | primitive operations. For example, you can interact and display data by | |
85a9b4ed | 760 | manipulating the contents of an Emacs buffer, but you can't pop-up and |
9401323e NJ |
761 | draw a window with a layout that is totally different to the Emacs |
762 | standard. | |
763 | ||
764 | This situation with a Guile application that supports the loading of | |
765 | arbitrary user code is similar, except perhaps even more so, because | |
766 | Guile also supports the loading of extension libraries written in C. | |
767 | This last point enables user code to add new primitive operations to | |
768 | Guile, and so to bypass the limitation present in Emacs Lisp. | |
769 | ||
770 | At this point, the distinction between an application developer and an | |
771 | application user becomes rather blurred. Instead of seeing yourself as | |
772 | a user extending an application, you could equally well say that you are | |
773 | developing a new application of your own using some of the primitive | |
774 | functionality provided by the original application. As such, all the | |
775 | discussions of the preceding sections of this chapter are relevant to | |
776 | how you can proceed with developing your extension. |