Merge branch 'master' into wip-manual-2
[bpt/guile.git] / doc / ref / libguile-smobs.texi
CommitLineData
3229f68b
MV
1@c -*-texinfo-*-
2@c This is part of the GNU Guile Reference Manual.
0f7e6c56 3@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010
3229f68b
MV
4@c Free Software Foundation, Inc.
5@c See the file guile.texi for copying conditions.
6
7@node Defining New Types (Smobs)
8@section Defining New Types (Smobs)
9
10@dfn{Smobs} are Guile's mechanism for adding new primitive types to
11the system. The term ``smob'' was coined by Aubrey Jaffer, who says
12it comes from ``small object'', referring to the fact that they are
13quite limited in size: they can hold just one pointer to a larger
14memory block plus 16 extra bits.
15
16To define a new smob type, the programmer provides Guile with some
17essential information about the type --- how to print it, how to
18garbage collect it, and so on --- and Guile allocates a fresh type tag
19for it. The programmer can then use @code{scm_c_define_gsubr} to make
20a set of C functions visible to Scheme code that create and operate on
21these objects.
22
23(You can find a complete version of the example code used in this
24section in the Guile distribution, in @file{doc/example-smob}. That
25directory includes a makefile and a suitable @code{main} function, so
26you can build a complete interactive Guile shell, extended with the
27datatypes described here.)
28
29@menu
30* Describing a New Type::
eb12b401 31* Creating Smob Instances::
3229f68b
MV
32* Type checking::
33* Garbage Collecting Smobs::
34* Garbage Collecting Simple Smobs::
35* Remembering During Operations::
36* Double Smobs::
37* The Complete Example::
38@end menu
39
40@node Describing a New Type
41@subsection Describing a New Type
42
43To define a new type, the programmer must write four functions to
44manage instances of the type:
45
46@table @code
47@item mark
48Guile will apply this function to each instance of the new type it
49encounters during garbage collection. This function is responsible for
50telling the collector about any other @code{SCM} values that the object
51has stored. The default smob mark function does nothing.
52@xref{Garbage Collecting Smobs}, for more details.
53
54@item free
55Guile will apply this function to each instance of the new type that is
56to be deallocated. The function should release all resources held by
57the object. This is analogous to the Java finalization method-- it is
58invoked at an unspecified time (when garbage collection occurs) after
59the object is dead. The default free function frees the smob data (if
60the size of the struct passed to @code{scm_make_smob_type} is non-zero)
61using @code{scm_gc_free}. @xref{Garbage Collecting Smobs}, for more
62details.
63
1a82e370
MV
64This function operates while the heap is in an inconsistent state and
65must therefore be careful. @xref{Smobs}, for details about what this
66function is allowed to do.
67
3229f68b
MV
68@item print
69Guile will apply this function to each instance of the new type to print
70the value, as for @code{display} or @code{write}. The default print
71function prints @code{#<NAME ADDRESS>} where @code{NAME} is the first
0f7e6c56 72argument passed to @code{scm_make_smob_type}.
3229f68b
MV
73
74@item equalp
75If Scheme code asks the @code{equal?} function to compare two instances
76of the same smob type, Guile calls this function. It should return
77@code{SCM_BOOL_T} if @var{a} and @var{b} should be considered
78@code{equal?}, or @code{SCM_BOOL_F} otherwise. If @code{equalp} is
79@code{NULL}, @code{equal?} will assume that two instances of this type are
80never @code{equal?} unless they are @code{eq?}.
81
82@end table
83
84To actually register the new smob type, call @code{scm_make_smob_type}.
85It returns a value of type @code{scm_t_bits} which identifies the new
86smob type.
87
818d24b5 88The four special functions described above are registered by calling
3229f68b
MV
89one of @code{scm_set_smob_mark}, @code{scm_set_smob_free},
90@code{scm_set_smob_print}, or @code{scm_set_smob_equalp}, as
91appropriate. Each function is intended to be used at most once per
92type, and the call should be placed immediately following the call to
93@code{scm_make_smob_type}.
94
95There can only be at most 256 different smob types in the system.
96Instead of registering a huge number of smob types (for example, one
97for each relevant C struct in your application), it is sometimes
8c3fa3e5 98better to register just one and implement a second layer of type
3229f68b 99dispatching on top of it. This second layer might use the 16 extra
8c3fa3e5 100bits to extend its type, for example.
3229f68b
MV
101
102Here is how one might declare and register a new type representing
103eight-bit gray-scale images:
104
105@example
106#include <libguile.h>
107
108struct image @{
109 int width, height;
110 char *pixels;
111
112 /* The name of this image */
113 SCM name;
114
115 /* A function to call when this image is
116 modified, e.g., to update the screen,
117 or SCM_BOOL_F if no action necessary */
118 SCM update_func;
119@};
120
121static scm_t_bits image_tag;
122
123void
124init_image_type (void)
125@{
126 image_tag = scm_make_smob_type ("image", sizeof (struct image));
127 scm_set_smob_mark (image_tag, mark_image);
128 scm_set_smob_free (image_tag, free_image);
129 scm_set_smob_print (image_tag, print_image);
130@}
131@end example
132
133
eb12b401
NJ
134@node Creating Smob Instances
135@subsection Creating Smob Instances
3229f68b 136
818d24b5
MV
137Normally, smobs can have one @emph{immediate} word of data. This word
138stores either a pointer to an additional memory block that holds the
139real data, or it might hold the data itself when it fits. The word is
140large enough for a @code{SCM} value, a pointer to @code{void}, or an
141integer that fits into a @code{size_t} or @code{ssize_t}.
3229f68b
MV
142
143You can also create smobs that have two or three immediate words, and
144when these words suffice to store all data, it is more efficient to use
145these super-sized smobs instead of using a normal smob plus a memory
146block. @xref{Double Smobs}, for their discussion.
147
fc038e5b
MV
148Guile provides functions for managing memory which are often helpful
149when implementing smobs. @xref{Memory Blocks}.
150
3229f68b
MV
151To retrieve the immediate word of a smob, you use the macro
152@code{SCM_SMOB_DATA}. It can be set with @code{SCM_SET_SMOB_DATA}.
153The 16 extra bits can be accessed with @code{SCM_SMOB_FLAGS} and
154@code{SCM_SET_SMOB_FLAGS}.
155
818d24b5 156The two macros @code{SCM_SMOB_DATA} and @code{SCM_SET_SMOB_DATA} treat
fc038e5b
MV
157the immediate word as if it were of type @code{scm_t_bits}, which is
158an unsigned integer type large enough to hold a pointer to
159@code{void}. Thus you can use these macros to store arbitrary
160pointers in the smob word.
161
162When you want to store a @code{SCM} value directly in the immediate
163word of a smob, you should use the macros @code{SCM_SMOB_OBJECT} and
164@code{SCM_SET_SMOB_OBJECT} to access it.
3229f68b
MV
165
166Creating a smob instance can be tricky when it consists of multiple
167steps that allocate resources and might fail. It is recommended that
168you go about creating a smob in the following way:
169
170@itemize
171@item
172Allocate the memory block for holding the data with
173@code{scm_gc_malloc}.
174@item
175Initialize it to a valid state without calling any functions that might
176cause a non-local exits. For example, initialize pointers to NULL.
177Also, do not store @code{SCM} values in it that must be protected.
178Initialize these fields with @code{SCM_BOOL_F}.
179
180A valid state is one that can be safely acted upon by the @emph{mark}
181and @emph{free} functions of your smob type.
182@item
183Create the smob using @code{SCM_NEWSMOB}, passing it the initialized
184memory block. (This step will always succeed.)
185@item
186Complete the initialization of the memory block by, for example,
187allocating additional resources and making it point to them.
188@end itemize
189
fc038e5b
MV
190This procedure ensures that the smob is in a valid state as soon as it
191exists, that all resources that are allocated for the smob are
192properly associated with it so that they can be properly freed, and
193that no @code{SCM} values that need to be protected are stored in it
72b3aa56 194while the smob does not yet completely exist and thus can not protect
fc038e5b 195them.
3229f68b
MV
196
197Continuing the example from above, if the global variable
198@code{image_tag} contains a tag returned by @code{scm_make_smob_type},
199here is how we could construct a smob whose immediate word contains a
200pointer to a freshly allocated @code{struct image}:
201
202@example
203SCM
204make_image (SCM name, SCM s_width, SCM s_height)
205@{
206 SCM smob;
207 struct image *image;
208 int width = scm_to_int (s_width);
209 int height = scm_to_int (s_height);
210
211 /* Step 1: Allocate the memory block.
212 */
45867c2a
NJ
213 image = (struct image *)
214 scm_gc_malloc (sizeof (struct image), "image");
3229f68b
MV
215
216 /* Step 2: Initialize it with straight code.
217 */
218 image->width = width;
219 image->height = height;
220 image->pixels = NULL;
221 image->name = SCM_BOOL_F;
222 image->update_func = SCM_BOOL_F;
223
224 /* Step 3: Create the smob.
225 */
818d24b5 226 SCM_NEWSMOB (smob, image_tag, image);
3229f68b
MV
227
228 /* Step 4: Finish the initialization.
229 */
230 image->name = name;
45867c2a
NJ
231 image->pixels =
232 scm_gc_malloc (width * height, "image pixels");
3229f68b
MV
233
234 return smob;
235@}
236@end example
237
238Let us look at what might happen when @code{make_image} is called.
239
240The conversions of @var{s_width} and @var{s_height} to @code{int}s might
241fail and signal an error, thus causing a non-local exit. This is not a
242problem since no resources have been allocated yet that would have to be
243freed.
244
245The allocation of @var{image} in step 1 might fail, but this is likewise
246no problem.
247
248Step 2 can not exit non-locally. At the end of it, the @var{image}
249struct is in a valid state for the @code{mark_image} and
250@code{free_image} functions (see below).
251
252Step 3 can not exit non-locally either. This is guaranteed by Guile.
253After it, @var{smob} contains a valid smob that is properly initialized
254and protected, and in turn can properly protect the Scheme values in its
255@var{image} struct.
256
257But before the smob is completely created, @code{SCM_NEWSMOB} might
258cause the garbage collector to run. During this garbage collection, the
259@code{SCM} values in the @var{image} struct would be invisible to Guile.
260It only gets to know about them via the @code{mark_image} function, but
261that function can not yet do its job since the smob has not been created
262yet. Thus, it is important to not store @code{SCM} values in the
263@var{image} struct until after the smob has been created.
264
265Step 4, finally, might fail and cause a non-local exit. In that case,
fc038e5b
MV
266the complete creation of the smob has not been successful, but it does
267nevertheless exist in a valid state. It will eventually be freed by
268the garbage collector, and all the resources that have been allocated
269for it will be correctly freed by @code{free_image}.
3229f68b
MV
270
271@node Type checking
272@subsection Type checking
273
818d24b5
MV
274Functions that operate on smobs should check that the passed
275@code{SCM} value indeed is a suitable smob before accessing its data.
276They can do this with @code{scm_assert_smob_type}.
3229f68b
MV
277
278For example, here is a simple function that operates on an image smob,
279and checks the type of its argument.
280
281@example
282SCM
283clear_image (SCM image_smob)
284@{
285 int area;
286 struct image *image;
287
818d24b5 288 scm_assert_smob_type (image_tag, image_smob);
3229f68b
MV
289
290 image = (struct image *) SCM_SMOB_DATA (image_smob);
291 area = image->width * image->height;
292 memset (image->pixels, 0, area);
293
294 /* Invoke the image's update function.
295 */
296 if (scm_is_true (image->update_func))
297 scm_call_0 (image->update_func);
298
299 scm_remember_upto_here_1 (image_smob);
300
301 return SCM_UNSPECIFIED;
302@}
303@end example
304
305See @ref{Remembering During Operations} for an explanation of the call
306to @code{scm_remember_upto_here_1}.
307
308
309@node Garbage Collecting Smobs
310@subsection Garbage Collecting Smobs
311
312Once a smob has been released to the tender mercies of the Scheme
313system, it must be prepared to survive garbage collection. Guile calls
314the @emph{mark} and @emph{free} functions of the smob to manage this.
315
316As described in more detail elsewhere (@pxref{Conservative GC}), every
317object in the Scheme system has a @dfn{mark bit}, which the garbage
318collector uses to tell live objects from dead ones. When collection
319starts, every object's mark bit is clear. The collector traces pointers
320through the heap, starting from objects known to be live, and sets the
321mark bit on each object it encounters. When it can find no more
322unmarked objects, the collector walks all objects, live and dead, frees
323those whose mark bits are still clear, and clears the mark bit on the
324others.
325
326The two main portions of the collection are called the @dfn{mark phase},
327during which the collector marks live objects, and the @dfn{sweep
328phase}, during which the collector frees all unmarked objects.
329
330The mark bit of a smob lives in a special memory region. When the
331collector encounters a smob, it sets the smob's mark bit, and uses the
332smob's type tag to find the appropriate @emph{mark} function for that
333smob. It then calls this @emph{mark} function, passing it the smob as
334its only argument.
335
336The @emph{mark} function is responsible for marking any other Scheme
337objects the smob refers to. If it does not do so, the objects' mark
338bits will still be clear when the collector begins to sweep, and the
339collector will free them. If this occurs, it will probably break, or at
340least confuse, any code operating on the smob; the smob's @code{SCM}
341values will have become dangling references.
342
343To mark an arbitrary Scheme object, the @emph{mark} function calls
344@code{scm_gc_mark}.
345
346Thus, here is how we might write @code{mark_image}:
347
348@example
349@group
350SCM
351mark_image (SCM image_smob)
352@{
353 /* Mark the image's name and update function. */
354 struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
355
356 scm_gc_mark (image->name);
357 scm_gc_mark (image->update_func);
358
359 return SCM_BOOL_F;
360@}
361@end group
362@end example
363
364Note that, even though the image's @code{update_func} could be an
365arbitrarily complex structure (representing a procedure and any values
366enclosed in its environment), @code{scm_gc_mark} will recurse as
367necessary to mark all its components. Because @code{scm_gc_mark} sets
368an object's mark bit before it recurses, it is not confused by
369circular structures.
370
371As an optimization, the collector will mark whatever value is returned
372by the @emph{mark} function; this helps limit depth of recursion during
373the mark phase. Thus, the code above should really be written as:
374@example
375@group
376SCM
377mark_image (SCM image_smob)
378@{
379 /* Mark the image's name and update function. */
380 struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
381
382 scm_gc_mark (image->name);
383 return image->update_func;
384@}
385@end group
386@end example
387
388
389Finally, when the collector encounters an unmarked smob during the sweep
390phase, it uses the smob's tag to find the appropriate @emph{free}
391function for the smob. It then calls that function, passing it the smob
392as its only argument.
393
394The @emph{free} function must release any resources used by the smob.
395However, it must not free objects managed by the collector; the
396collector will take care of them. For historical reasons, the return
397type of the @emph{free} function should be @code{size_t}, an unsigned
398integral type; the @emph{free} function should always return zero.
399
400Here is how we might write the @code{free_image} function for the image
401smob type:
402@example
403size_t
404free_image (SCM image_smob)
405@{
406 struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
407
45867c2a
NJ
408 scm_gc_free (image->pixels,
409 image->width * image->height,
410 "image pixels");
3229f68b
MV
411 scm_gc_free (image, sizeof (struct image), "image");
412
413 return 0;
414@}
415@end example
416
417During the sweep phase, the garbage collector will clear the mark bits
418on all live objects. The code which implements a smob need not do this
419itself.
420
421There is no way for smob code to be notified when collection is
422complete.
423
424It is usually a good idea to minimize the amount of processing done
425during garbage collection; keep the @emph{mark} and @emph{free}
426functions very simple. Since collections occur at unpredictable times,
427it is easy for any unusual activity to interfere with normal code.
428
429
430@node Garbage Collecting Simple Smobs
431@subsection Garbage Collecting Simple Smobs
432
433It is often useful to define very simple smob types --- smobs which have
434no data to mark, other than the cell itself, or smobs whose immediate
435data word is simply an ordinary Scheme object, to be marked recursively.
436Guile provides some functions to handle these common cases; you can use
437this function as your smob type's @emph{mark} function, if your smob's
438structure is simple enough.
439
440If the smob refers to no other Scheme objects, then no action is
441necessary; the garbage collector has already marked the smob cell
442itself. In that case, you can use zero as your mark function.
443
fc038e5b
MV
444If the smob refers to exactly one other Scheme object via its first
445immediate word, you can use @code{scm_markcdr} as its mark function.
446Its definition is simply:
3229f68b 447
fc038e5b
MV
448@smallexample
449SCM
450scm_markcdr (SCM obj)
451@{
452 return SCM_SMOB_OBJECT (obj);
453@}
454@end smallexample
3229f68b
MV
455
456@node Remembering During Operations
457@subsection Remembering During Operations
1176df85 458@cindex remembering
3229f68b
MV
459
460It's important that a smob is visible to the garbage collector
461whenever its contents are being accessed. Otherwise it could be freed
462while code is still using it.
463
464For example, consider a procedure to convert image data to a list of
465pixel values.
466
467@example
468SCM
469image_to_list (SCM image_smob)
470@{
471 struct image *image;
472 SCM lst;
473 int i;
818d24b5
MV
474
475 scm_assert_smob_type (image_tag, image_smob);
3229f68b
MV
476
477 image = (struct image *) SCM_SMOB_DATA (image_smob);
478 lst = SCM_EOL;
479 for (i = image->width * image->height - 1; i >= 0; i--)
480 lst = scm_cons (scm_from_char (image->pixels[i]), lst);
481
482 scm_remember_upto_here_1 (image_smob);
483 return lst;
484@}
485@end example
486
487In the loop, only the @code{image} pointer is used and the C compiler
488has no reason to keep the @code{image_smob} value anywhere. If
489@code{scm_cons} results in a garbage collection, @code{image_smob} might
490not be on the stack or anywhere else and could be freed, leaving the
491loop accessing freed data. The use of @code{scm_remember_upto_here_1}
492prevents this, by creating a reference to @code{image_smob} after all
493data accesses.
494
495There's no need to do the same for @code{lst}, since that's the return
496value and the compiler will certainly keep it in a register or
497somewhere throughout the routine.
498
499The @code{clear_image} example previously shown (@pxref{Type checking})
500also used @code{scm_remember_upto_here_1} for this reason.
501
502It's only in quite rare circumstances that a missing
503@code{scm_remember_upto_here_1} will bite, but when it happens the
504consequences are serious. Fortunately the rule is simple: whenever
505calling a Guile library function or doing something that might, ensure
fc038e5b 506that the @code{SCM} of a smob is referenced past all accesses to its
3229f68b
MV
507insides. Do this by adding an @code{scm_remember_upto_here_1} if
508there are no other references.
509
510In a multi-threaded program, the rule is the same. As far as a given
511thread is concerned, a garbage collection still only occurs within a
512Guile library function, not at an arbitrary time. (Guile waits for all
513threads to reach one of its library functions, and holds them there
514while the collector runs.)
515
516@node Double Smobs
517@subsection Double Smobs
518
519Smobs are called smob because they are small: they normally have only
fc038e5b
MV
520room for one @code{void*} or @code{SCM} value plus 16 bits. The
521reason for this is that smobs are directly implemented by using the
522low-level, two-word cells of Guile that are also used to implement
0f7e6c56 523pairs, for example. (@pxref{Data Representation} for the
8680d53b
AW
524details.) One word of the two-word cells is used for
525@code{SCM_SMOB_DATA} (or @code{SCM_SMOB_OBJECT}), the other contains
526the 16-bit type tag and the 16 extra bits.
3229f68b
MV
527
528In addition to the fundamental two-word cells, Guile also has
529four-word cells, which are appropriately called @dfn{double cells}.
530You can use them for @dfn{double smobs} and get two more immediate
531words of type @code{scm_t_bits}.
532
533A double smob is created with @code{SCM_NEWSMOB2} or
534@code{SCM_NEWSMOB3} instead of @code{SCM_NEWSMOB}. Its immediate
fc038e5b
MV
535words can be retrieved as @code{scm_t_bits} with
536@code{SCM_SMOB_DATA_2} and @code{SCM_SMOB_DATA_3} in addition to
537@code{SCM_SMOB_DATA}. Unsurprisingly, the words can be set to
538@code{scm_t_bits} values with @code{SCM_SET_SMOB_DATA_2} and
539@code{SCM_SET_SMOB_DATA_3}.
540
541Of course there are also @code{SCM_SMOB_OBJECT_2},
542@code{SCM_SMOB_OBJECT_3}, @code{SCM_SET_SMOB_OBJECT_2}, and
543@code{SCM_SET_SMOB_OBJECT_3}.
3229f68b
MV
544
545@node The Complete Example
546@subsection The Complete Example
547
548Here is the complete text of the implementation of the image datatype,
549as presented in the sections above. We also provide a definition for
550the smob's @emph{print} function, and make some objects and functions
551static, to clarify exactly what the surrounding code is using.
552
553As mentioned above, you can find this code in the Guile distribution, in
554@file{doc/example-smob}. That directory includes a makefile and a
555suitable @code{main} function, so you can build a complete interactive
556Guile shell, extended with the datatypes described here.)
557
558@example
559/* file "image-type.c" */
560
561#include <stdlib.h>
562#include <libguile.h>
563
564static scm_t_bits image_tag;
565
566struct image @{
567 int width, height;
568 char *pixels;
569
570 /* The name of this image */
571 SCM name;
572
573 /* A function to call when this image is
574 modified, e.g., to update the screen,
575 or SCM_BOOL_F if no action necessary */
576 SCM update_func;
577@};
578
579static SCM
580make_image (SCM name, SCM s_width, SCM s_height)
581@{
582 SCM smob;
583 struct image *image;
584 int width = scm_to_int (s_width);
585 int height = scm_to_int (s_height);
586
587 /* Step 1: Allocate the memory block.
588 */
45867c2a
NJ
589 image = (struct image *)
590 scm_gc_malloc (sizeof (struct image), "image");
3229f68b
MV
591
592 /* Step 2: Initialize it with straight code.
593 */
594 image->width = width;
595 image->height = height;
596 image->pixels = NULL;
597 image->name = SCM_BOOL_F;
598 image->update_func = SCM_BOOL_F;
599
600 /* Step 3: Create the smob.
601 */
818d24b5 602 SCM_NEWSMOB (smob, image_tag, image);
3229f68b
MV
603
604 /* Step 4: Finish the initialization.
605 */
606 image->name = name;
45867c2a
NJ
607 image->pixels =
608 scm_gc_malloc (width * height, "image pixels");
3229f68b
MV
609
610 return smob;
611@}
612
613SCM
614clear_image (SCM image_smob)
615@{
616 int area;
617 struct image *image;
618
818d24b5 619 scm_assert_smob_type (image_tag, image_smob);
3229f68b
MV
620
621 image = (struct image *) SCM_SMOB_DATA (image_smob);
622 area = image->width * image->height;
623 memset (image->pixels, 0, area);
624
625 /* Invoke the image's update function.
626 */
627 if (scm_is_true (image->update_func))
628 scm_call_0 (image->update_func);
629
630 scm_remember_upto_here_1 (image_smob);
631
632 return SCM_UNSPECIFIED;
633@}
634
635static SCM
636mark_image (SCM image_smob)
637@{
638 /* Mark the image's name and update function. */
639 struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
640
641 scm_gc_mark (image->name);
642 return image->update_func;
643@}
644
645static size_t
646free_image (SCM image_smob)
647@{
648 struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
649
45867c2a
NJ
650 scm_gc_free (image->pixels,
651 image->width * image->height,
652 "image pixels");
3229f68b
MV
653 scm_gc_free (image, sizeof (struct image), "image");
654
655 return 0;
656@}
657
658static int
659print_image (SCM image_smob, SCM port, scm_print_state *pstate)
660@{
661 struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
662
663 scm_puts ("#<image ", port);
664 scm_display (image->name, port);
665 scm_puts (">", port);
666
667 /* non-zero means success */
668 return 1;
669@}
670
671void
672init_image_type (void)
673@{
674 image_tag = scm_make_smob_type ("image", sizeof (struct image));
675 scm_set_smob_mark (image_tag, mark_image);
676 scm_set_smob_free (image_tag, free_image);
677 scm_set_smob_print (image_tag, print_image);
678
679 scm_c_define_gsubr ("clear-image", 1, 0, 0, clear_image);
680 scm_c_define_gsubr ("make-image", 3, 0, 0, make_image);
681@}
682@end example
683
684Here is a sample build and interaction with the code from the
685@file{example-smob} directory, on the author's machine:
686
687@example
688zwingli:example-smob$ make CC=gcc
689gcc `guile-config compile` -c image-type.c -o image-type.o
690gcc `guile-config compile` -c myguile.c -o myguile.o
691gcc image-type.o myguile.o `guile-config link` -o myguile
692zwingli:example-smob$ ./myguile
693guile> make-image
694#<primitive-procedure make-image>
695guile> (define i (make-image "Whistler's Mother" 100 100))
696guile> i
697#<image Whistler's Mother>
698guile> (clear-image i)
699guile> (clear-image 4)
700ERROR: In procedure clear-image in expression (clear-image 4):
48d8f659 701ERROR: Wrong type (expecting image): 4
3229f68b
MV
702ABORT: (wrong-type-arg)
703
704Type "(backtrace)" to get more information.
705guile>
706@end example